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/jsview/js_water_flow_sections.h"
17 
18 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
19 #include "core/components_ng/pattern/waterflow/water_flow_sections.h"
20 
21 namespace OHOS::Ace::Framework {
SetMarginProperty(const JSRef<JSObject> & paddingObj,NG::MarginProperty & margin)22 bool SetMarginProperty(const JSRef<JSObject>& paddingObj, NG::MarginProperty& margin)
23 {
24     std::optional<CalcDimension> left;
25     std::optional<CalcDimension> right;
26     std::optional<CalcDimension> top;
27     std::optional<CalcDimension> bottom;
28     JSViewAbstract::ParseMarginOrPaddingCorner(paddingObj, top, bottom, left, right);
29     bool isMarginObject = false;
30     if (top.has_value()) {
31         if (top.value().Unit() == DimensionUnit::CALC) {
32             margin.top = NG::CalcLength(top.value().CalcValue());
33         } else {
34             margin.top = NG::CalcLength(top.value());
35         }
36         isMarginObject = true;
37     }
38     if (bottom.has_value()) {
39         if (bottom.value().Unit() == DimensionUnit::CALC) {
40             margin.bottom = NG::CalcLength(bottom.value().CalcValue());
41         } else {
42             margin.bottom = NG::CalcLength(bottom.value());
43         }
44         isMarginObject = true;
45     }
46     if (left.has_value()) {
47         if (left.value().Unit() == DimensionUnit::CALC) {
48             margin.left = NG::CalcLength(left.value().CalcValue());
49         } else {
50             margin.left = NG::CalcLength(left.value());
51         }
52         isMarginObject = true;
53     }
54     if (right.has_value()) {
55         if (right.value().Unit() == DimensionUnit::CALC) {
56             margin.right = NG::CalcLength(right.value().CalcValue());
57         } else {
58             margin.right = NG::CalcLength(right.value());
59         }
60         isMarginObject = true;
61     }
62     return isMarginObject;
63 }
64 
ParseMargin(const JSRef<JSVal> & jsValue,NG::MarginProperty & margin)65 void ParseMargin(const JSRef<JSVal>& jsValue, NG::MarginProperty& margin)
66 {
67     if (jsValue->IsObject()) {
68         auto marginObj = JSRef<JSObject>::Cast(jsValue);
69         if (SetMarginProperty(marginObj, margin)) {
70             return;
71         }
72     }
73 
74     CalcDimension length;
75     if (!JSViewAbstract::ParseJsDimensionVp(jsValue, length)) {
76         length.Reset();
77     }
78     if (length.Unit() == DimensionUnit::CALC) {
79         margin.SetEdges(NG::CalcLength(length.CalcValue()));
80     } else {
81         margin.SetEdges(NG::CalcLength(length));
82     }
83 }
84 
85 namespace {
ParseGaps(const JSRef<JSObject> & obj,NG::WaterFlowSections::Section & section)86 void ParseGaps(const JSRef<JSObject>& obj, NG::WaterFlowSections::Section& section)
87 {
88     if (obj->HasProperty("columnsGap")) {
89         auto columnsGap = obj->GetProperty("columnsGap");
90         CalcDimension colGap;
91         if (!JSViewAbstract::ParseJsDimensionVp(columnsGap, colGap) || colGap.Value() < 0) {
92             colGap.SetValue(0.0);
93         }
94         section.columnsGap = colGap;
95     }
96 
97     if (obj->HasProperty("rowsGap")) {
98         auto rowsGap = obj->GetProperty("rowsGap");
99         CalcDimension rowGap;
100         if (!JSViewAbstract::ParseJsDimensionVp(rowsGap, rowGap) || rowGap.Value() < 0) {
101             rowGap.SetValue(0.0);
102         }
103         section.rowsGap = rowGap;
104     }
105 
106     if (obj->HasProperty("margin")) {
107         auto margin = obj->GetProperty("margin");
108         NG::MarginProperty marginProperty;
109         ParseMargin(margin, marginProperty);
110         section.margin = marginProperty;
111     }
112 }
113 } // namespace
114 
ParseSectionOptions(const JSCallbackInfo & args,const JSRef<JSVal> & jsValue,NG::WaterFlowSections::Section & section)115 bool JSWaterFlowSections::ParseSectionOptions(
116     const JSCallbackInfo& args, const JSRef<JSVal>& jsValue, NG::WaterFlowSections::Section& section)
117 {
118     if (!jsValue->IsObject()) {
119         LOGW("The arg must be object");
120         return false;
121     }
122 
123     JSRef<JSObject> obj = JSRef<JSObject>::Cast(jsValue);
124     if (!obj->HasProperty("itemsCount")) {
125         return false;
126     }
127     auto itemsCount = obj->GetProperty("itemsCount");
128     JSViewAbstract::ParseJsInteger(itemsCount, section.itemsCount);
129     if (section.itemsCount < 0) {
130         LOGW("itemsCount can not be less than 0");
131         return false;
132     }
133 
134     if (obj->HasProperty("crossCount")) {
135         auto crossCount = obj->GetProperty("crossCount");
136         int32_t crossCountValue = 1;
137         JSViewAbstract::ParseJsInteger(crossCount, crossCountValue);
138         if (crossCountValue <= 0) {
139             crossCountValue = 1;
140         }
141         section.crossCount = crossCountValue;
142     }
143 
144     ParseGaps(obj, section);
145 
146     if (!obj->HasProperty("onGetItemMainSizeByIndex")) {
147         return true;
148     }
149     auto getSizeByIndex = obj->GetProperty("onGetItemMainSizeByIndex");
150     if (!getSizeByIndex->IsFunction()) {
151         return true;
152     }
153 
154     auto onGetItemMainSizeByIndex = [execCtx = args.GetExecutionContext(),
155                                         func = AceType::MakeRefPtr<JsFunction>(
156                                             JSRef<JSObject>(), JSRef<JSFunc>::Cast(getSizeByIndex))](int32_t index) {
157         JSRef<JSVal> itemIndex = JSRef<JSVal>::Make(ToJSValue(index));
158         auto result = func->ExecuteJS(1, &itemIndex);
159         if (!result->IsNumber()) {
160             return 0.0f;
161         }
162 
163         return result->ToNumber<float>();
164     };
165     section.onGetItemMainSizeByIndex = std::move(onGetItemMainSizeByIndex);
166     return true;
167 }
168 } // namespace OHOS::Ace::Framework
169