• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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