• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_grid_row.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/log/ace_scoring_log.h"
20 #include "base/log/ace_trace.h"
21 #include "base/memory/referenced.h"
22 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
23 #include "bridge/declarative_frontend/jsview/models/grid_row_model_impl.h"
24 #include "core/components_ng/base/view_stack_processor.h"
25 #include "core/components_ng/pattern/grid_row/grid_row_model_ng.h"
26 #include "core/components_v2/grid_layout/grid_container_util_class.h"
27 
28 namespace OHOS::Ace {
GetInstance()29 GridRowModel* GridRowModel::GetInstance()
30 {
31 #ifdef NG_BUILD
32     static NG::GridRowModelNG instance;
33     return &instance;
34 #else
35     if (Container::IsCurrentUseNewPipeline()) {
36         static NG::GridRowModelNG instance;
37         return &instance;
38     } else {
39         static Framework::GridRowModelImpl instance;
40         return &instance;
41     }
42 #endif
43 }
44 } // namespace OHOS::Ace
45 
46 namespace OHOS::Ace::Framework {
47 namespace {
48 
49 constexpr size_t MAX_NUMBER_BREAKPOINT = 6;
50 
InheritGridRowOption(const RefPtr<V2::GridContainerSize> & gridContainerSize,std::optional<int32_t> (& containerSizeArray)[MAX_NUMBER_BREAKPOINT])51 void InheritGridRowOption(const RefPtr<V2::GridContainerSize>& gridContainerSize,
52     std::optional<int32_t> (&containerSizeArray)[MAX_NUMBER_BREAKPOINT])
53 {
54     if (!containerSizeArray[0].has_value()) {
55         containerSizeArray[0] = V2::DEFAULT_COLUMN_NUMBER;
56     }
57     for (size_t i = 1; i < MAX_NUMBER_BREAKPOINT; i++) {
58         if (!containerSizeArray[i].has_value()) {
59             containerSizeArray[i] = containerSizeArray[i - 1].value();
60         }
61     }
62     gridContainerSize->xs = containerSizeArray[0].value();
63     gridContainerSize->sm = containerSizeArray[1].value();
64     gridContainerSize->md = containerSizeArray[2].value();
65     gridContainerSize->lg = containerSizeArray[3].value();
66     gridContainerSize->xl = containerSizeArray[4].value();
67     gridContainerSize->xxl = containerSizeArray[5].value();
68 }
69 
InheritGridRowGutterOption(const RefPtr<V2::Gutter> & gutter,std::optional<CalcDimension> (& gutterSizeArray)[MAX_NUMBER_BREAKPOINT],bool isHorizontal)70 void InheritGridRowGutterOption(const RefPtr<V2::Gutter>& gutter,
71     std::optional<CalcDimension> (&gutterSizeArray)[MAX_NUMBER_BREAKPOINT], bool isHorizontal)
72 {
73     if (!gutterSizeArray[0].has_value()) {
74         gutterSizeArray[0] = CalcDimension(0);
75     }
76     for (size_t i = 1; i < MAX_NUMBER_BREAKPOINT; i++) {
77         if (!gutterSizeArray[i].has_value()) {
78             gutterSizeArray[i] = gutterSizeArray[i - 1].value();
79         }
80     }
81     if (isHorizontal) {
82         gutter->xXs = gutterSizeArray[0].value();
83         gutter->xSm = gutterSizeArray[1].value();
84         gutter->xMd = gutterSizeArray[2].value();
85         gutter->xLg = gutterSizeArray[3].value();
86         gutter->xXl = gutterSizeArray[4].value();
87         gutter->xXXl = gutterSizeArray[5].value();
88         return;
89     }
90     gutter->yXs = gutterSizeArray[0].value();
91     gutter->ySm = gutterSizeArray[1].value();
92     gutter->yMd = gutterSizeArray[2].value();
93     gutter->yLg = gutterSizeArray[3].value();
94     gutter->yXl = gutterSizeArray[4].value();
95     gutter->yXXl = gutterSizeArray[5].value();
96 }
97 
ParseGutterObject(const JSRef<JSVal> & gutterObject,RefPtr<V2::Gutter> & gutter,bool isHorizontal)98 void ParseGutterObject(const JSRef<JSVal>& gutterObject, RefPtr<V2::Gutter>& gutter, bool isHorizontal)
99 {
100     CalcDimension dim;
101     if (JSContainerBase::ParseJsDimensionVp(gutterObject, dim)) {
102         isHorizontal ? gutter->SetXGutter(dim) : gutter->SetYGutter(dim);
103         return;
104     }
105     if (!gutterObject->IsObject()) {
106         return;
107     }
108     std::optional<CalcDimension> gutterOptions[MAX_NUMBER_BREAKPOINT];
109     auto gutterParam = JSRef<JSObject>::Cast(gutterObject);
110     auto xs = gutterParam->GetProperty("xs");
111     CalcDimension xsDimension;
112     if (JSContainerBase::ParseJsDimensionVp(xs, xsDimension)) {
113         gutterOptions[0] = xsDimension;
114     }
115     auto sm = gutterParam->GetProperty("sm");
116     CalcDimension smDimension;
117     if (JSContainerBase::ParseJsDimensionVp(sm, smDimension)) {
118         gutterOptions[1] = smDimension;
119     }
120     auto md = gutterParam->GetProperty("md");
121     CalcDimension mdDimension;
122     if (JSContainerBase::ParseJsDimensionVp(md, mdDimension)) {
123         gutterOptions[2] = mdDimension;
124     }
125     auto lg = gutterParam->GetProperty("lg");
126     CalcDimension lgDimension;
127     if (JSContainerBase::ParseJsDimensionVp(lg, lgDimension)) {
128         gutterOptions[3] = lgDimension;
129     }
130     auto xl = gutterParam->GetProperty("xl");
131     CalcDimension xlDimension;
132     if (JSContainerBase::ParseJsDimensionVp(xl, xlDimension)) {
133         gutterOptions[4] = xlDimension;
134     }
135     auto xxl = gutterParam->GetProperty("xxl");
136     CalcDimension xxlDimension;
137     if (JSContainerBase::ParseJsDimensionVp(xxl, xxlDimension)) {
138         gutterOptions[5] = xxlDimension;
139     }
140     InheritGridRowGutterOption(gutter, gutterOptions, isHorizontal);
141 }
142 
ParserGutter(const JSRef<JSVal> & jsValue)143 RefPtr<V2::Gutter> ParserGutter(const JSRef<JSVal>& jsValue)
144 {
145     CalcDimension result;
146     if (JSContainerBase::ParseJsDimensionVp(jsValue, result)) {
147         auto gutter = AceType::MakeRefPtr<V2::Gutter>(result);
148         return gutter;
149     } else {
150         if (!jsValue->IsObject()) {
151             return AceType::MakeRefPtr<V2::Gutter>();
152         }
153         auto paramGutter = JSRef<JSObject>::Cast(jsValue);
154         auto xObject = paramGutter->GetProperty("x");
155         auto yObject = paramGutter->GetProperty("y");
156         auto gutter = AceType::MakeRefPtr<V2::Gutter>();
157         ParseGutterObject(xObject, gutter, true);
158         ParseGutterObject(yObject, gutter, false);
159         return gutter;
160     }
161 }
162 
ParserColumns(const JSRef<JSVal> & jsValue)163 RefPtr<V2::GridContainerSize> ParserColumns(const JSRef<JSVal>& jsValue)
164 {
165     if (jsValue->IsNumber()) {
166         auto columnNumber = jsValue->ToNumber<int32_t>();
167         return columnNumber > 0 ? AceType::MakeRefPtr<V2::GridContainerSize>(columnNumber)
168                                 : AceType::MakeRefPtr<V2::GridContainerSize>();
169     } else if (jsValue->IsObject()) {
170         auto gridContainerSize = AceType::MakeRefPtr<V2::GridContainerSize>(12);
171         auto gridParam = JSRef<JSObject>::Cast(jsValue);
172         std::optional<int32_t> containerSizeArray[MAX_NUMBER_BREAKPOINT];
173         auto xs = gridParam->GetProperty("xs");
174         if (xs->IsNumber() && xs->ToNumber<int32_t>() > 0) {
175             containerSizeArray[0] = xs->ToNumber<int32_t>();
176         }
177         auto sm = gridParam->GetProperty("sm");
178         if (sm->IsNumber() && sm->ToNumber<int32_t>() > 0) {
179             containerSizeArray[1] = sm->ToNumber<int32_t>();
180         }
181         auto md = gridParam->GetProperty("md");
182         if (md->IsNumber() && md->ToNumber<int32_t>() > 0) {
183             containerSizeArray[2] = md->ToNumber<int32_t>();
184         }
185         auto lg = gridParam->GetProperty("lg");
186         if (lg->IsNumber() && lg->ToNumber<int32_t>() > 0) {
187             containerSizeArray[3] = lg->ToNumber<int32_t>();
188         }
189         auto xl = gridParam->GetProperty("xl");
190         if (xl->IsNumber() && xl->ToNumber<int32_t>() > 0) {
191             containerSizeArray[4] = xl->ToNumber<int32_t>();
192         }
193         auto xxl = gridParam->GetProperty("xxl");
194         if (xxl->IsNumber() && xxl->ToNumber<int32_t>() > 0) {
195             containerSizeArray[5] = xxl->ToNumber<int32_t>();
196         }
197         InheritGridRowOption(gridContainerSize, containerSizeArray);
198         return gridContainerSize;
199     } else {
200         return AceType::MakeRefPtr<V2::GridContainerSize>();
201     }
202 }
203 
ParserBreakpoints(const JSRef<JSVal> & jsValue)204 RefPtr<V2::BreakPoints> ParserBreakpoints(const JSRef<JSVal>& jsValue)
205 {
206     if (!jsValue->IsObject()) {
207         return AceType::MakeRefPtr<V2::BreakPoints>();
208     }
209     auto breakpoints = JSRef<JSObject>::Cast(jsValue);
210     auto value = breakpoints->GetProperty("value");
211     auto reference = breakpoints->GetProperty("reference");
212     auto breakpoint = AceType::MakeRefPtr<V2::BreakPoints>();
213     if (reference->IsNumber()) {
214         breakpoint->reference = static_cast<V2::BreakPointsReference>(reference->ToNumber<int32_t>());
215     }
216     if (value->IsArray()) {
217         JSRef<JSArray> array = JSRef<JSArray>::Cast(value);
218         breakpoint->breakpoints.clear();
219         if (array->Length() > MAX_NUMBER_BREAKPOINT - 1) {
220             return breakpoint;
221         }
222         double width = -1.0;
223         for (size_t i = 0; i < array->Length(); i++) {
224             JSRef<JSVal> threshold = array->GetValueAt(i);
225             if (threshold->IsString() || threshold->IsNumber()) {
226                 CalcDimension valueDimension;
227                 JSContainerBase::ParseJsDimensionVp(threshold, valueDimension);
228                 if (GreatNotEqual(width, valueDimension.Value())) {
229                     return breakpoint;
230                 }
231                 width = valueDimension.Value();
232                 breakpoint->breakpoints.push_back(threshold->ToString());
233             }
234         }
235     }
236     return breakpoint;
237 }
238 
ParserDirection(const JSRef<JSVal> & jsValue)239 V2::GridRowDirection ParserDirection(const JSRef<JSVal>& jsValue)
240 {
241     V2::GridRowDirection direction(V2::GridRowDirection::Row);
242     if (jsValue->IsNumber()) {
243         direction = static_cast<V2::GridRowDirection>(jsValue->ToNumber<int32_t>());
244     }
245     return direction;
246 }
247 
248 } // namespace
249 
Create(const JSCallbackInfo & info)250 void JSGridRow::Create(const JSCallbackInfo& info)
251 {
252     if (info[0]->IsObject()) {
253         auto gridRow = JSRef<JSObject>::Cast(info[0]);
254         auto columns = gridRow->GetProperty("columns");
255         auto gutter = gridRow->GetProperty("gutter");
256         auto breakpoints = gridRow->GetProperty("breakpoints");
257         auto direction = gridRow->GetProperty("direction");
258 
259         auto parsedColumns = ParserColumns(columns);
260         auto parsedGutter = ParserGutter(gutter);
261         auto parsedBreakpoints = ParserBreakpoints(breakpoints);
262         auto parsedDirection = ParserDirection(direction);
263         GridRowModel::GetInstance()->Create(parsedColumns, parsedGutter, parsedBreakpoints, parsedDirection);
264     } else {
265         GridRowModel::GetInstance()->Create();
266     }
267 }
268 
JsBreakpointEvent(const JSCallbackInfo & info)269 void JSGridRow::JsBreakpointEvent(const JSCallbackInfo& info)
270 {
271     if (!info[0]->IsFunction()) {
272         return;
273     }
274     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
275     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
276     auto onBreakpointChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
277                                   const std::string& value) {
278         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
279         ACE_SCORING_EVENT("GridRow.onBreakpointChange");
280         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(value));
281         PipelineContext::SetCallBackNode(node);
282         func->ExecuteJS(1, &newJSVal);
283     };
284     GridRowModel::GetInstance()->SetOnBreakPointChange(onBreakpointChange);
285 }
286 
Height(const JSCallbackInfo & info)287 void JSGridRow::Height(const JSCallbackInfo& info)
288 {
289     JSViewAbstract::JsHeight(info[0]);
290     GridRowModel::GetInstance()->SetHeight();
291 }
292 
AlignItems(const JSCallbackInfo & info)293 void JSGridRow::AlignItems(const JSCallbackInfo& info)
294 {
295     if (info[0]->IsNumber()) {
296         auto value = info[0]->ToNumber<int32_t>();
297         ParseAlignItems(value);
298     } else if (info[0]->IsUndefined()) {
299         GridRowModel::GetInstance()->SetAlignItems(FlexAlign::FLEX_START);
300     }
301 }
302 
ParseAlignItems(int32_t alignItem)303 void JSGridRow::ParseAlignItems(int32_t alignItem)
304 {
305     if (alignItem == static_cast<int32_t>(FlexAlign::FLEX_START) ||
306         alignItem == static_cast<int32_t>(FlexAlign::FLEX_END) ||
307         alignItem == static_cast<int32_t>(FlexAlign::CENTER) || alignItem == static_cast<int32_t>(FlexAlign::STRETCH)) {
308         GridRowModel::GetInstance()->SetAlignItems(static_cast<FlexAlign>(alignItem));
309     } else if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
310         GridRowModel::GetInstance()->SetAlignItems(FlexAlign::FLEX_START);
311     }
312 }
313 
JSBind(BindingTarget globalObj)314 void JSGridRow::JSBind(BindingTarget globalObj)
315 {
316     JSClass<JSGridRow>::Declare("GridRow");
317     JSClass<JSGridRow>::StaticMethod("create", &JSGridRow::Create);
318     JSClass<JSGridRow>::StaticMethod("onBreakpointChange", &JSGridRow::JsBreakpointEvent);
319     JSClass<JSGridRow>::StaticMethod("height", &JSGridRow::Height);
320     JSClass<JSGridRow>::StaticMethod("alignItems", &JSGridRow::AlignItems);
321     JSClass<JSGridRow>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
322     JSClass<JSGridRow>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
323     JSClass<JSGridRow>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
324     JSClass<JSGridRow>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
325     JSClass<JSGridRow>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
326     JSClass<JSGridRow>::InheritAndBind<JSContainerBase>(globalObj);
327 }
328 
329 } // namespace OHOS::Ace::Framework
330