1 /*
2 * Copyright (c) 2021-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_page_transition.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "bridge/declarative_frontend/engine/functions/js_page_transition_function.h"
20 #include "bridge/declarative_frontend/jsview/models/page_transition_model_impl.h"
21 #include "core/components_ng/pattern/stage/page_transition_model_ng.h"
22
23 namespace OHOS::Ace {
24 std::unique_ptr<PageTransitionModel> PageTransitionModel::instance_ = nullptr;
25
GetInstance()26 PageTransitionModel* PageTransitionModel::GetInstance()
27 {
28 if (!instance_) {
29 #ifdef NG_BUILD
30 instance_.reset(new NG::PageTransitionModelNG());
31 #else
32 if (Container::IsCurrentUseNewPipeline()) {
33 instance_.reset(new NG::PageTransitionModelNG());
34 } else {
35 instance_.reset(new Framework::PageTransitionModelImpl());
36 }
37 #endif
38 }
39 return instance_.get();
40 }
41 } // namespace OHOS::Ace
42
43 namespace OHOS::Ace::Framework {
44
JSBind(BindingTarget globalObj)45 void JSPageTransition::JSBind(BindingTarget globalObj)
46 {
47 JSClass<JSPageTransition>::Declare("PageTransition");
48 MethodOptions opt = MethodOptions::NONE;
49 JSClass<JSPageTransition>::StaticMethod("create", &JSPageTransition::Create, opt);
50 JSClass<JSPageTransition>::StaticMethod("pop", &JSPageTransition::Pop);
51 JSClass<JSPageTransition>::Bind<>(globalObj);
52
53 JSClass<JSPageTransitionEnter>::Declare("PageTransitionEnter");
54 JSClass<JSPageTransitionEnter>::StaticMethod("create", &JSPageTransitionEnter::Create, opt);
55 JSClass<JSPageTransitionEnter>::StaticMethod("slide", &JSPageTransition::Slide);
56 JSClass<JSPageTransitionEnter>::StaticMethod("translate", &JSPageTransition::Translate);
57 JSClass<JSPageTransitionEnter>::StaticMethod("scale", &JSPageTransition::Scale);
58 JSClass<JSPageTransitionEnter>::StaticMethod("opacity", &JSPageTransition::Opacity);
59 JSClass<JSPageTransitionEnter>::StaticMethod("onEnter", &JSPageTransition::JsHandlerOnEnter);
60 JSClass<JSPageTransitionEnter>::StaticMethod("pop", &JSPageTransitionEnter::Pop);
61 JSClass<JSPageTransitionEnter>::Bind<>(globalObj);
62
63 JSClass<JSPageTransitionExit>::Declare("PageTransitionExit");
64 JSClass<JSPageTransitionExit>::StaticMethod("create", &JSPageTransitionExit::Create, opt);
65 JSClass<JSPageTransitionExit>::StaticMethod("slide", &JSPageTransition::Slide);
66 JSClass<JSPageTransitionExit>::StaticMethod("translate", &JSPageTransition::Translate);
67 JSClass<JSPageTransitionExit>::StaticMethod("scale", &JSPageTransition::Scale);
68 JSClass<JSPageTransitionExit>::StaticMethod("opacity", &JSPageTransition::Opacity);
69 JSClass<JSPageTransitionExit>::StaticMethod("onExit", &JSPageTransition::JsHandlerOnExit);
70 JSClass<JSPageTransitionExit>::StaticMethod("pop", &JSPageTransitionExit::Pop);
71 JSClass<JSPageTransitionExit>::Bind<>(globalObj);
72 }
73
Slide(const JSCallbackInfo & info)74 void JSPageTransition::Slide(const JSCallbackInfo& info)
75 {
76 LOGD("JSPageTransition::Slide");
77 if (info.Length() > 0 && info[0]->IsNumber()) {
78 auto effect = info[0]->ToNumber<int32_t>();
79
80 if (effect >= static_cast<int32_t>(SlideEffect::LEFT) && effect <= static_cast<int32_t>(SlideEffect::BOTTOM)) {
81 PageTransitionModel::GetInstance()->SetSlideEffect(static_cast<SlideEffect>(effect));
82 }
83 }
84 }
85
Translate(const JSCallbackInfo & info)86 void JSPageTransition::Translate(const JSCallbackInfo& info)
87 {
88 LOGD("JSPageTransitionTranslate");
89 if (info.Length() > 0 && info[0]->IsObject()) {
90 auto args = JsonUtil::ParseJsonString(info[0]->ToString());
91 if (!args || args->IsNull()) {
92 LOGE("JSTransition Translate failed json value is nullptr or json object is null");
93 return;
94 }
95
96 NG::TranslateOptions option;
97
98 Dimension length;
99 if (JSViewAbstract::ParseJsonDimensionVp(args->GetValue("x"), length)) {
100 option.x = length;
101 }
102 if (JSViewAbstract::ParseJsonDimensionVp(args->GetValue("y"), length)) {
103 option.y = length;
104 }
105 if (JSViewAbstract::ParseJsonDimensionVp(args->GetValue("z"), length)) {
106 option.z = length;
107 }
108 PageTransitionModel::GetInstance()->SetTranslateEffect(option);
109 }
110 }
111
Scale(const JSCallbackInfo & info)112 void JSPageTransition::Scale(const JSCallbackInfo& info)
113 {
114 LOGD("JSPageTransition::Scale");
115 if (info.Length() > 0 && info[0]->IsObject()) {
116 auto args = JsonUtil::ParseJsonString(info[0]->ToString());
117 if (!args || args->IsNull()) {
118 LOGE("JSTransition Scale failed, json value is nullptr or json object is null");
119 return;
120 }
121
122 // default: x, y, z (1.0, 1.0, 1.0)
123 double scaleX = 1.0;
124 double scaleY = 1.0;
125 double scaleZ = 1.0;
126 JSViewAbstract::ParseJsonDouble(args->GetValue("x"), scaleX);
127 JSViewAbstract::ParseJsonDouble(args->GetValue("y"), scaleY);
128 JSViewAbstract::ParseJsonDouble(args->GetValue("z"), scaleZ);
129 // default centerX, centerY 50% 50%;
130 Dimension centerX = 0.5_pct;
131 Dimension centerY = 0.5_pct;
132
133 // if specify centerX
134 Dimension length;
135 if (JSViewAbstract::ParseJsonDimensionVp(args->GetValue("centerX"), length)) {
136 centerX = length;
137 }
138 // if specify centerY
139 if (JSViewAbstract::ParseJsonDimensionVp(args->GetValue("centerY"), length)) {
140 centerY = length;
141 }
142 NG::ScaleOptions option(
143 static_cast<float>(scaleX), static_cast<float>(scaleY), static_cast<float>(scaleZ), centerX, centerY);
144 PageTransitionModel::GetInstance()->SetScaleEffect(option);
145 }
146 }
147
Opacity(const JSCallbackInfo & info)148 void JSPageTransition::Opacity(const JSCallbackInfo& info)
149 {
150 LOGD("JSPageTransition::Opacity");
151 if (info.Length() < 1) {
152 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
153 return;
154 }
155 double opacity = 0.0;
156 if (!JSViewAbstract::ParseJsDouble(info[0], opacity)) {
157 return;
158 }
159 PageTransitionModel::GetInstance()->SetOpacityEffect(static_cast<float>(opacity));
160 }
161
JsHandlerOnEnter(const JSCallbackInfo & info)162 void JSPageTransition::JsHandlerOnEnter(const JSCallbackInfo& info)
163 {
164 LOGD("JSPageTransition::JsHandlerOnEnter");
165 if (info.Length() < 1 || !info[0]->IsFunction()) {
166 LOGE("JsHandlerOnEnter info.Length < 0 or info[0] is not function");
167 return;
168 }
169
170 RefPtr<JsPageTransitionFunction> function =
171 AceType::MakeRefPtr<JsPageTransitionFunction>(JSRef<JSFunc>::Cast(info[0]));
172
173 auto onEnterHandler = [execCtx = info.GetExecutionContext(), func = std::move(function)](
174 RouteType type, const float& progress) {
175 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
176 ACE_SCORING_EVENT("PageTransition.onEnter");
177 func->Execute(type, progress);
178 };
179
180 PageTransitionModel::GetInstance()->SetOnEnter(std::move(onEnterHandler));
181 }
182
JsHandlerOnExit(const JSCallbackInfo & info)183 void JSPageTransition::JsHandlerOnExit(const JSCallbackInfo& info)
184 {
185 LOGD("JSPageTransition::JsHandlerOnExit");
186 if (info.Length() < 1 || !info[0]->IsFunction()) {
187 LOGE("JsHandlerOnExit info.Length < 0 or info[0] is not function");
188 return;
189 }
190
191 RefPtr<JsPageTransitionFunction> function =
192 AceType::MakeRefPtr<JsPageTransitionFunction>(JSRef<JSFunc>::Cast(info[0]));
193
194 auto onExitHandler = [execCtx = info.GetExecutionContext(), func = std::move(function)](
195 RouteType type, const float& progress) {
196 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
197 ACE_SCORING_EVENT("PageTransition.onExit");
198 func->Execute(type, progress);
199 };
200
201 PageTransitionModel::GetInstance()->SetOnExit(std::move(onExitHandler));
202 }
203
Create(const JSCallbackInfo & info)204 void JSPageTransition::Create(const JSCallbackInfo& info)
205 {
206 LOGD("JSPageTransition::JSTransition::Create");
207 PageTransitionModel::GetInstance()->Create();
208 }
209
Pop()210 void JSPageTransition::Pop()
211 {
212 LOGD("JSPageTransition::Pop");
213 PageTransitionModel::GetInstance()->Pop();
214 }
215
ParseTransitionOption(const std::unique_ptr<JsonValue> & transitionArgs)216 PageTransitionOption JSPageTransition::ParseTransitionOption(const std::unique_ptr<JsonValue>& transitionArgs)
217 {
218 PageTransitionOption option;
219 const int32_t defaultDuration = 1000;
220 option.duration = defaultDuration;
221 option.curve = Curves::LINEAR;
222 if (transitionArgs && !transitionArgs->IsNull()) {
223 option.duration = transitionArgs->GetInt("duration", defaultDuration);
224 if (option.duration < 0) {
225 option.duration = defaultDuration;
226 }
227 option.delay = transitionArgs->GetInt("delay", 0);
228 auto routeTypeTmp = transitionArgs->GetInt("type", static_cast<int32_t>(RouteType::NONE));
229 if (routeTypeTmp >= static_cast<int32_t>(RouteType::NONE) &&
230 routeTypeTmp <= static_cast<int32_t>(RouteType::POP)) {
231 option.routeType = static_cast<RouteType>(routeTypeTmp);
232 } else {
233 LOGW("CreateTransition RouteType out of range");
234 }
235
236 auto curveArgs = transitionArgs->GetValue("curve");
237 if (curveArgs->IsString()) {
238 option.curve = CreateCurve(curveArgs->GetString());
239 } else if (curveArgs->IsObject()) {
240 auto curveString = curveArgs->GetValue("__curveString");
241 if (curveString) {
242 option.curve = CreateCurve(curveString->GetString());
243 }
244 }
245 }
246 return option;
247 }
248
Create(const JSCallbackInfo & info)249 void JSPageTransitionEnter::Create(const JSCallbackInfo& info)
250 {
251 LOGD("JSPageTransitionEnter::Create");
252 if (info.Length() > 0 && info[0]->IsObject()) {
253 auto transitionArgs = JsonUtil::ParseJsonString(info[0]->ToString());
254 auto option = ParseTransitionOption(transitionArgs);
255 PageTransitionModel::GetInstance()->CreateTransition(PageTransitionType::ENTER, option);
256 }
257 }
258
Create(const JSCallbackInfo & info)259 void JSPageTransitionExit::Create(const JSCallbackInfo& info)
260 {
261 LOGD("JSPageTransitionExit::Create");
262 if (info.Length() > 0 && info[0]->IsObject()) {
263 auto transitionArgs = JsonUtil::ParseJsonString(info[0]->ToString());
264 auto option = ParseTransitionOption(transitionArgs);
265 PageTransitionModel::GetInstance()->CreateTransition(PageTransitionType::EXIT, option);
266 }
267 }
268
269 } // namespace OHOS::Ace::Framework