1 /*
2  * Copyright (c) 2023 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 "core/interfaces/native/node/calendar_picker_modifier.h"
17 
18 #include "base/json/json_util.h"
19 #include "core/components_ng/base/frame_node.h"
20 #include "core/components_ng/base/view_abstract.h"
21 #include "core/pipeline/base/element_register.h"
22 #include "frameworks/core/components_ng/pattern/calendar_picker/calendar_picker_model_ng.h"
23 #include "frameworks/core/components_ng/pattern/picker/picker_type_define.h"
24 
25 namespace OHOS::Ace::NG {
26 namespace {
27 constexpr int NUM_0 = 0;
28 constexpr int NUM_1 = 1;
29 constexpr int NUM_2 = 2;
30 } // namespace
SetHintRadius(ArkUINodeHandle node,float radius,int32_t unit)31 void SetHintRadius(ArkUINodeHandle node, float radius, int32_t unit)
32 {
33     auto* frameNode = reinterpret_cast<FrameNode*>(node);
34     CHECK_NULL_VOID(frameNode);
35     Dimension radiusDimension(radius, static_cast<DimensionUnit>(unit));
36     CalendarPickerModelNG::SetHintRadiusWithNode(frameNode, radiusDimension);
37 }
38 
GetHintRadius(ArkUINodeHandle node)39 float GetHintRadius(ArkUINodeHandle node)
40 {
41     auto* frameNode = reinterpret_cast<FrameNode*>(node);
42     CHECK_NULL_RETURN(frameNode, 0.0f);
43     return CalendarPickerModelNG::GetHintRadius(frameNode).Value();
44 }
45 
SetSelectedDate(ArkUINodeHandle node,uint32_t year,uint32_t month,uint32_t day)46 void SetSelectedDate(ArkUINodeHandle node, uint32_t year, uint32_t month, uint32_t day)
47 {
48     auto* frameNode = reinterpret_cast<FrameNode*>(node);
49     CHECK_NULL_VOID(frameNode);
50     CalendarPickerModelNG::SetSelectDateWithNode(frameNode, year, month, day);
51 }
52 
GetSelectedDate(ArkUINodeHandle node)53 ArkUISelectedDateType GetSelectedDate(ArkUINodeHandle node)
54 {
55     ArkUISelectedDateType selectedDate = { 0, 0, 0 };
56     auto* frameNode = reinterpret_cast<FrameNode*>(node);
57     CHECK_NULL_RETURN(frameNode, selectedDate);
58     auto pickDate = CalendarPickerModelNG::GetSelectDateWithNode(frameNode);
59     selectedDate.year = static_cast<uint32_t>(pickDate.GetYear());
60     selectedDate.month = static_cast<uint32_t>(pickDate.GetMonth());
61     selectedDate.day = static_cast<uint32_t>(pickDate.GetDay());
62     return selectedDate;
63 }
64 
ResetSelectedDate(ArkUINodeHandle node)65 void ResetSelectedDate(ArkUINodeHandle node)
66 {
67     auto* frameNode = reinterpret_cast<FrameNode*>(node);
68     CHECK_NULL_VOID(frameNode);
69     auto currentDate = PickerDate::Current();
70     CalendarPickerModelNG::SetSelectDateWithNode(
71         frameNode, currentDate.GetYear(), currentDate.GetMonth(), currentDate.GetDay());
72 }
73 
SetTextStyleWithWeightEnum(ArkUINodeHandle node,uint32_t color,float fontSize,int32_t fontSizeUnit,int32_t fontWeight)74 void SetTextStyleWithWeightEnum(
75     ArkUINodeHandle node, uint32_t color, float fontSize, int32_t fontSizeUnit, int32_t fontWeight)
76 {
77     auto* frameNode = reinterpret_cast<FrameNode*>(node);
78     CHECK_NULL_VOID(frameNode);
79     NG::PickerTextStyle textStyle;
80     textStyle.textColor = Color(color);
81     Dimension fontSizeDimension(fontSize, DimensionUnit::FP);
82     textStyle.fontSize = fontSizeDimension;
83     textStyle.fontWeight = static_cast<Ace::FontWeight>(fontWeight);
84     CalendarPickerModelNG::SetTextStyle(frameNode, textStyle);
85 }
86 
SetTextStyle(ArkUINodeHandle node,uint32_t color,const char * fontSize,const char * fontweight)87 void SetTextStyle(ArkUINodeHandle node, uint32_t color, const char* fontSize, const char* fontweight)
88 {
89     auto* frameNode = reinterpret_cast<FrameNode*>(node);
90     CHECK_NULL_VOID(frameNode);
91     NG::PickerTextStyle textStyle;
92     textStyle.textColor = Color(color);
93     CalcDimension fontSizeDimension =
94         StringUtils::StringToCalcDimension(std::string(fontSize), false, DimensionUnit::FP);
95     if (fontSizeDimension.Unit() == DimensionUnit::PERCENT) {
96         textStyle.fontSize = Dimension(-1);
97     } else {
98         textStyle.fontSize = fontSizeDimension;
99     }
100     textStyle.fontWeight = StringUtils::StringToFontWeight(fontweight, FontWeight::NORMAL);
101     CalendarPickerModelNG::SetTextStyle(frameNode, textStyle);
102 }
103 
GetTextStyle(ArkUINodeHandle node)104 ArkUICalendarTextStyleType GetTextStyle(ArkUINodeHandle node)
105 {
106     ArkUICalendarTextStyleType textStyle = { Color::BLACK.GetValue(), 0.0f, 0 };
107     auto* frameNode = reinterpret_cast<FrameNode*>(node);
108     CHECK_NULL_RETURN(frameNode, textStyle);
109     auto currentTextStyle = CalendarPickerModelNG::GetTextStyle(frameNode);
110     textStyle.fontColor = currentTextStyle.textColor.has_value() ? currentTextStyle.textColor.value().GetValue()
111                                                                         : Color::BLACK.GetValue();
112     textStyle.fontSize = currentTextStyle.fontSize.has_value() ? currentTextStyle.fontSize.value().Value() : 0.0f;
113     textStyle.fontWeight = currentTextStyle.fontWeight.has_value()
114                                       ? static_cast<int32_t>(currentTextStyle.fontWeight.value())
115                                       : static_cast<int32_t>(FontWeight::NORMAL);
116     return textStyle;
117 }
118 
ResetTextStyle(ArkUINodeHandle node)119 void ResetTextStyle(ArkUINodeHandle node)
120 {
121     auto* frameNode = reinterpret_cast<FrameNode*>(node);
122     CHECK_NULL_VOID(frameNode);
123     auto pipeline = PipelineBase::GetCurrentContext();
124     CHECK_NULL_VOID(pipeline);
125     RefPtr<CalendarTheme> calendarTheme = pipeline->GetTheme<CalendarTheme>();
126     CHECK_NULL_VOID(calendarTheme);
127     NG::PickerTextStyle textStyle;
128     textStyle.fontSize = calendarTheme->GetEntryFontSize();
129     textStyle.textColor = calendarTheme->GetEntryFontColor();
130     textStyle.fontWeight = FontWeight::NORMAL;
131     CalendarPickerModelNG::SetTextStyle(frameNode, textStyle);
132 }
133 
SetEdgeAlign(ArkUINodeHandle node,const ArkUI_Float32 * values,const int * units,int32_t size,int32_t alignType)134 void SetEdgeAlign(ArkUINodeHandle node, const ArkUI_Float32* values, const int* units, int32_t size, int32_t alignType)
135 {
136     auto* frameNode = reinterpret_cast<FrameNode*>(node);
137     CHECK_NULL_VOID(frameNode);
138     if (size < NUM_2) {
139         return;
140     }
141 
142     Dimension dx = Dimension(values[NUM_0], static_cast<OHOS::Ace::DimensionUnit>(units[NUM_0]));
143     Dimension dy = Dimension(values[NUM_1], static_cast<OHOS::Ace::DimensionUnit>(units[NUM_1]));
144     NG::CalendarEdgeAlign align = static_cast<NG::CalendarEdgeAlign>(alignType);
145     DimensionOffset offset = DimensionOffset(dx, dy);
146     CalendarPickerModelNG::SetEdgeAlign(frameNode, align, offset);
147 }
148 
GetEdgeAlign(ArkUINodeHandle node)149 ArkUIEdgeAlignType GetEdgeAlign(ArkUINodeHandle node)
150 {
151     ArkUIEdgeAlignType align = { 0, 0.0f, 0.0f };
152     auto* frameNode = reinterpret_cast<FrameNode*>(node);
153     CHECK_NULL_RETURN(frameNode, align);
154     auto offset = CalendarPickerModelNG::GetEdgeOffset(frameNode);
155     align.alignType = static_cast<int32_t>(CalendarPickerModelNG::GetEdgeAlignType(frameNode));
156     align.offsetX = offset.GetX().ConvertToVp();
157     align.offsetY = offset.GetY().ConvertToVp();
158     return align;
159 }
160 
ResetEdgeAlign(ArkUINodeHandle node)161 void ResetEdgeAlign(ArkUINodeHandle node)
162 {
163     auto* frameNode = reinterpret_cast<FrameNode*>(node);
164     CHECK_NULL_VOID(frameNode);
165     NG::CalendarEdgeAlign alignType = NG::CalendarEdgeAlign::EDGE_ALIGN_END;
166     DimensionOffset offset;
167     CalendarPickerModelNG::SetEdgeAlign(frameNode, alignType, offset);
168 }
169 
SetCalendarPickerHeight(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit)170 void SetCalendarPickerHeight(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit)
171 {
172     auto* frameNode = reinterpret_cast<FrameNode*>(node);
173     CHECK_NULL_VOID(frameNode);
174     DimensionUnit unitEnum = static_cast<OHOS::Ace::DimensionUnit>(unit);
175     Dimension height = Dimension(value, unitEnum);
176     if (height.IsValid()) {
177         ViewAbstract::SetHeight(frameNode, CalcLength(height));
178     } else {
179         CalendarPickerModelNG::ClearHeight(frameNode);
180     }
181 }
182 
ResetCalendarPickerHeight(ArkUINodeHandle node)183 void ResetCalendarPickerHeight(ArkUINodeHandle node)
184 {
185     auto* frameNode = reinterpret_cast<FrameNode*>(node);
186     CHECK_NULL_VOID(frameNode);
187     CalendarPickerModelNG::ClearHeight(frameNode);
188 }
189 
SetCalendarPickerBorderColor(ArkUINodeHandle node,ArkUI_Uint32 color)190 void SetCalendarPickerBorderColor(ArkUINodeHandle node, ArkUI_Uint32 color)
191 {
192     auto* frameNode = reinterpret_cast<FrameNode*>(node);
193     CHECK_NULL_VOID(frameNode);
194     ViewAbstract::SetBorderColor(frameNode, Color(color));
195 }
196 
ResetCalendarPickerBorderColor(ArkUINodeHandle node)197 void ResetCalendarPickerBorderColor(ArkUINodeHandle node)
198 {
199     auto* frameNode = reinterpret_cast<FrameNode*>(node);
200     CHECK_NULL_VOID(frameNode);
201     CalendarPickerModelNG::ClearBorderColor(frameNode);
202 }
203 
SetCalendarPickerBorderRadius(ArkUINodeHandle node,const ArkUI_Float32 value,const ArkUI_Int32 unit)204 void SetCalendarPickerBorderRadius(ArkUINodeHandle node, const ArkUI_Float32 value, const ArkUI_Int32 unit)
205 {
206     auto *frameNode = reinterpret_cast<FrameNode *>(node);
207     CHECK_NULL_VOID(frameNode);
208     Dimension radius =
209         Dimension(static_cast<double>(value), static_cast<OHOS::Ace::DimensionUnit>(unit));
210     ViewAbstract::SetBorderRadius(frameNode, radius);
211 }
212 
ResetCalendarPickerBorderRadius(ArkUINodeHandle node)213 void ResetCalendarPickerBorderRadius(ArkUINodeHandle node)
214 {
215     auto* frameNode = reinterpret_cast<FrameNode*>(node);
216     CHECK_NULL_VOID(frameNode);
217     CalendarPickerModelNG::ClearBorderRadius(frameNode);
218 }
219 
ResetCalendarPickerBorderWidth(ArkUINodeHandle node)220 void ResetCalendarPickerBorderWidth(ArkUINodeHandle node)
221 {
222     auto* frameNode = reinterpret_cast<FrameNode*>(node);
223     CHECK_NULL_VOID(frameNode);
224     CalendarPickerModelNG::ClearBorderWidth(frameNode);
225 }
226 
IsPaddingValid(NG::PaddingProperty & paddings,CalcLength topDim,CalcLength rightDim,CalcLength bottomDim,CalcLength leftDim)227 bool IsPaddingValid(NG::PaddingProperty& paddings, CalcLength topDim,
228     CalcLength rightDim, CalcLength bottomDim, CalcLength leftDim)
229 {
230     bool hasValue = false;
231     if (topDim.IsValid()) {
232         paddings.top = std::optional<CalcLength>(topDim);
233         hasValue = true;
234     }
235     if (bottomDim.IsValid()) {
236         paddings.bottom = std::optional<CalcLength>(bottomDim);
237         hasValue = true;
238     }
239     if (leftDim.IsValid()) {
240         paddings.left = std::optional<CalcLength>(leftDim);
241         hasValue = true;
242     }
243     if (rightDim.IsValid()) {
244         paddings.right = std::optional<CalcLength>(rightDim);
245         hasValue = true;
246     }
247     return hasValue;
248 }
249 
SetCalendarPickerPadding(ArkUINodeHandle node,const struct ArkUISizeType * top,const struct ArkUISizeType * right,const struct ArkUISizeType * bottom,const struct ArkUISizeType * left)250 void SetCalendarPickerPadding(ArkUINodeHandle node, const struct ArkUISizeType* top, const struct ArkUISizeType* right,
251     const struct ArkUISizeType* bottom, const struct ArkUISizeType* left)
252 {
253     auto* frameNode = reinterpret_cast<FrameNode*>(node);
254     CHECK_NULL_VOID(frameNode);
255     CalcLength topDim;
256     CalcLength rightDim;
257     CalcLength bottomDim;
258     CalcLength leftDim;
259     if (top->string != nullptr) {
260         topDim = CalcLength(top->string);
261     } else {
262         topDim = CalcLength(top->value, static_cast<DimensionUnit>(top->unit));
263     }
264     if (right->string != nullptr) {
265         rightDim = CalcLength(right->string);
266     } else {
267         rightDim = CalcLength(right->value, static_cast<DimensionUnit>(right->unit));
268     }
269     if (bottom->string != nullptr) {
270         bottomDim = CalcLength(bottom->string);
271     } else {
272         bottomDim = CalcLength(bottom->value, static_cast<DimensionUnit>(bottom->unit));
273     }
274     if (left->string != nullptr) {
275         leftDim = CalcLength(left->string);
276     } else {
277         leftDim = CalcLength(left->value, static_cast<DimensionUnit>(left->unit));
278     }
279     NG::PaddingProperty paddings;
280     paddings.top = std::optional<CalcLength>();
281     paddings.bottom = std::optional<CalcLength>();
282     paddings.left = std::optional<CalcLength>();
283     paddings.right = std::optional<CalcLength>();
284 
285     if (IsPaddingValid(paddings, topDim, rightDim, bottomDim, leftDim)) {
286         CalendarPickerModelNG::SetPadding(frameNode, paddings);
287     } else {
288         CalendarPickerModelNG::ClearPadding(frameNode);
289     }
290 }
291 
ResetCalendarPickerPadding(ArkUINodeHandle node)292 void ResetCalendarPickerPadding(ArkUINodeHandle node)
293 {
294     auto* frameNode = reinterpret_cast<FrameNode*>(node);
295     CHECK_NULL_VOID(frameNode);
296     CalendarPickerModelNG::ClearPadding(frameNode);
297 }
298 
SetCalendarPickerBorder(ArkUINodeHandle node,uint32_t color)299 void SetCalendarPickerBorder(ArkUINodeHandle node, uint32_t color)
300 {
301     auto* frameNode = reinterpret_cast<FrameNode*>(node);
302     CHECK_NULL_VOID(frameNode);
303 
304     ViewAbstract::SetBorderColor(frameNode, Color(color));
305 }
306 
ResetCalendarPickerBorder(ArkUINodeHandle node)307 void ResetCalendarPickerBorder(ArkUINodeHandle node)
308 {
309     auto* frameNode = reinterpret_cast<FrameNode*>(node);
310     CHECK_NULL_VOID(frameNode);
311 
312     auto pipeline = PipelineBase::GetCurrentContext();
313     CHECK_NULL_VOID(pipeline);
314     RefPtr<CalendarTheme> calendarTheme = pipeline->GetTheme<CalendarTheme>();
315     CHECK_NULL_VOID(calendarTheme);
316     ViewAbstract::SetBorderWidth(frameNode, calendarTheme->GetEntryBorderWidth());
317     ViewAbstract::SetBorderColor(frameNode, calendarTheme->GetEntryBorderColor());
318     ViewAbstract::SetBorderRadius(frameNode, calendarTheme->GetEntryBorderRadius());
319     ViewAbstract::SetBorderStyle(frameNode, BorderStyle::SOLID);
320 }
321 
322 namespace NodeModifier {
GetCalendarPickerModifier()323 const ArkUICalendarPickerModifier* GetCalendarPickerModifier()
324 {
325     static const ArkUICalendarPickerModifier modifier = { SetHintRadius, SetSelectedDate, ResetSelectedDate,
326         SetTextStyleWithWeightEnum, SetTextStyle, ResetTextStyle, SetEdgeAlign, ResetEdgeAlign,
327         SetCalendarPickerPadding, ResetCalendarPickerPadding, SetCalendarPickerBorder, ResetCalendarPickerBorder,
328         GetHintRadius, GetSelectedDate, GetTextStyle, GetEdgeAlign, SetCalendarPickerHeight, ResetCalendarPickerHeight,
329         SetCalendarPickerBorderColor, ResetCalendarPickerBorderColor, SetCalendarPickerBorderRadius,
330         ResetCalendarPickerBorderRadius, ResetCalendarPickerBorderWidth };
331 
332     return &modifier;
333 }
334 
GetCJUICalendarPickerModifier()335 const CJUICalendarPickerModifier* GetCJUICalendarPickerModifier()
336 {
337     static const CJUICalendarPickerModifier modifier = { SetHintRadius, SetSelectedDate, ResetSelectedDate,
338         SetTextStyleWithWeightEnum, SetTextStyle, ResetTextStyle, SetEdgeAlign, ResetEdgeAlign,
339         SetCalendarPickerPadding, ResetCalendarPickerPadding, SetCalendarPickerBorder, ResetCalendarPickerBorder,
340         GetHintRadius, GetSelectedDate, GetTextStyle, GetEdgeAlign, SetCalendarPickerHeight, ResetCalendarPickerHeight,
341         SetCalendarPickerBorderColor, ResetCalendarPickerBorderColor, SetCalendarPickerBorderRadius,
342         ResetCalendarPickerBorderRadius, ResetCalendarPickerBorderWidth };
343 
344     return &modifier;
345 }
346 
ParseDateByStr(const std::string & date,ArkUISelectedDateType & selectedDate)347 void ParseDateByStr(const std::string& date, ArkUISelectedDateType& selectedDate)
348 {
349     auto json = JsonUtil::ParseJsonString(date);
350     if (!json || json->IsNull()) {
351         return;
352     }
353     auto year = json->GetValue("year");
354     if (year && year->IsNumber()) {
355         uint32_t yearVal = year->GetInt() > 0 ? static_cast<uint32_t>(year->GetInt()) : 0;
356         selectedDate.year = yearVal; // local date start from 1900
357     }
358     auto month = json->GetValue("month");
359     if (month && month->IsNumber()) {
360         uint32_t monthVal = month->GetInt() > 0 ? static_cast<uint32_t>(month->GetInt()) : 0;
361         selectedDate.month = monthVal;
362     }
363     auto day = json->GetValue("day");
364     if (day && day->IsNumber()) {
365         uint32_t dayVal = day->GetInt() > 0 ? static_cast<uint32_t>(day->GetInt()) : 0;
366         selectedDate.day = dayVal;
367     }
368 }
369 
SetCalendarPickerOnChange(ArkUINodeHandle node,void * extraParam)370 void SetCalendarPickerOnChange(ArkUINodeHandle node, void* extraParam)
371 {
372     auto* frameNode = reinterpret_cast<FrameNode*>(node);
373     CHECK_NULL_VOID(frameNode);
374     auto onEvent = [node, extraParam](const std::string& dateStr) {
375         ArkUINodeEvent event;
376         event.kind = COMPONENT_ASYNC_EVENT;
377         event.extraParam = reinterpret_cast<intptr_t>(extraParam);
378         ArkUISelectedDateType selectedDate;
379         selectedDate.year = 0;
380         selectedDate.month = 0;
381         selectedDate.day = 0;
382         ParseDateByStr(dateStr, selectedDate);
383         event.componentAsyncEvent.subKind = ON_CALENDAR_PICKER_CHANGE;
384         event.componentAsyncEvent.data[NUM_0].u32 = selectedDate.year;
385         event.componentAsyncEvent.data[NUM_1].u32 = selectedDate.month;
386         event.componentAsyncEvent.data[NUM_2].u32 = selectedDate.day;
387         SendArkUIAsyncEvent(&event);
388     };
389     CalendarPickerModelNG::SetOnChangeWithNode(frameNode, std::move(onEvent));
390 }
391 } // namespace NodeModifier
392 } // namespace OHOS::Ace::NG
393