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/components_ng/pattern/calendar_picker/calendar_picker_model_ng.h"
17 
18 #include "base/i18n/localization.h"
19 #include "core/components/theme/icon_theme.h"
20 #include "core/components_ng/base/view_stack_processor.h"
21 #include "core/components_ng/pattern/button/button_pattern.h"
22 #include "core/components_ng/pattern/flex/flex_layout_pattern.h"
23 #include "core/components_ng/pattern/flex/flex_layout_property.h"
24 #include "core/components_ng/pattern/image/image_pattern.h"
25 #include "core/components_ng/pattern/text/text_pattern.h"
26 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
27 
28 namespace OHOS::Ace::NG {
29 constexpr int32_t YEAR_NODE_INDEX = 0;
30 constexpr int32_t MONTH_NODE_INDEX = 2;
31 constexpr int32_t DAY_NODE_INDEX = 4;
32 constexpr int32_t DATE_NODE_COUNT = 3;
33 constexpr int32_t ONE_DIGIT_BOUNDARY = 10;
34 constexpr float DEFAULT_HINT_RADIUS = 16.0f;
35 static int32_t yearNodeIndex_ = 0;
36 static int32_t monthNodeIndex_ = 2;
37 static int32_t dayNodeIndex_ = 4;
Create(const CalendarSettingData & settingData)38 void CalendarPickerModelNG::Create(const CalendarSettingData& settingData)
39 {
40     auto* stack = ViewStackProcessor::GetInstance();
41     auto nodeId = stack->ClaimNodeId();
42     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::CALENDAR_PICKER_ETS_TAG, nodeId);
43     auto pickerNode = CalendarPickerModelNG::CreateNode(nodeId, settingData);
44     stack->Push(pickerNode);
45 }
46 
CreateFrameNode(int32_t nodeId)47 RefPtr<FrameNode> CalendarPickerModelNG::CreateFrameNode(int32_t nodeId)
48 {
49     NG::CalendarSettingData settingData;
50     return CalendarPickerModelNG::CreateNode(nodeId, settingData);
51 }
52 
LayoutPicker(const RefPtr<CalendarPickerPattern> & pickerPattern,RefPtr<FrameNode> & pickerNode,const CalendarSettingData & settingData,const RefPtr<CalendarTheme> & theme)53 void CalendarPickerModelNG::LayoutPicker(const RefPtr<CalendarPickerPattern>& pickerPattern,
54     RefPtr<FrameNode>& pickerNode, const CalendarSettingData& settingData, const RefPtr<CalendarTheme>& theme)
55 {
56     auto textDirection = pickerNode->GetLayoutProperty()->GetNonAutoLayoutDirection();
57     if (!pickerPattern->HasContentNode()) {
58         auto contentNode = CalendarPickerModelNG::CreateCalendarNodeChild(
59             pickerPattern->GetContentId(), settingData, theme, textDirection);
60         CHECK_NULL_VOID(contentNode);
61         contentNode->MountToParent(pickerNode);
62     } else {
63         pickerPattern->SetDate(settingData.selectedDate.ToString(true));
64     }
65     auto flexNode = CalendarPickerModelNG::CreateButtonFlexChild(pickerPattern->GetButtonFlexId(), theme);
66     CHECK_NULL_VOID(flexNode);
67     flexNode->MountToParent(pickerNode);
68     if (!pickerPattern->HasAddNode()) {
69         auto addNode = CalendarPickerModelNG::CreateButtonChild(pickerPattern->GetAddId(), true, theme, textDirection);
70         CHECK_NULL_VOID(addNode);
71         addNode->MountToParent(flexNode, 0, true);
72     }
73     if (!pickerPattern->HasSubNode()) {
74         auto subNode = CalendarPickerModelNG::CreateButtonChild(pickerPattern->GetSubId(), false, theme, textDirection);
75         CHECK_NULL_VOID(subNode);
76         subNode->MountToParent(flexNode, 1, true);
77     }
78 }
79 
CreateButtonChild(int32_t id,bool isAdd,const RefPtr<CalendarTheme> & theme,TextDirection textDirection)80 RefPtr<FrameNode> CalendarPickerModelNG::CreateButtonChild(
81     int32_t id, bool isAdd, const RefPtr<CalendarTheme>& theme, TextDirection textDirection)
82 {
83     auto buttonNode =
84         FrameNode::GetOrCreateFrameNode(V2::BUTTON_ETS_TAG, id, []() { return AceType::MakeRefPtr<ButtonPattern>(); });
85     CHECK_NULL_RETURN(buttonNode, nullptr);
86     auto buttonEventHub = buttonNode->GetEventHub<ButtonEventHub>();
87     CHECK_NULL_RETURN(buttonEventHub, nullptr);
88     buttonEventHub->SetStateEffect(true);
89 
90     auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
91     CHECK_NULL_RETURN(buttonLayoutProperty, nullptr);
92     buttonLayoutProperty->UpdateType(ButtonType::NORMAL);
93 
94     auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
95     CHECK_NULL_RETURN(buttonPattern, nullptr);
96 
97     buttonNode->GetLayoutProperty()->UpdateUserDefinedIdealSize(
98         CalcSize(CalcLength(theme->GetEntryButtonWidth()), std::nullopt));
99     buttonNode->GetLayoutProperty()->UpdateLayoutWeight(1);
100     BorderWidthProperty borderWidth;
101     auto isRtl = textDirection == TextDirection::RTL;
102     if (isAdd) {
103         if (isRtl) {
104             borderWidth.rightDimen = theme->GetEntryBorderWidth();
105         } else {
106             borderWidth.leftDimen = theme->GetEntryBorderWidth();
107         }
108         borderWidth.bottomDimen = theme->GetEntryBorderWidth() / 2;
109     } else {
110         if (isRtl) {
111             borderWidth.rightDimen = theme->GetEntryBorderWidth();
112         } else {
113             borderWidth.leftDimen = theme->GetEntryBorderWidth();
114         }
115         borderWidth.topDimen = theme->GetEntryBorderWidth() / 2;
116     }
117     buttonNode->GetLayoutProperty()->UpdateBorderWidth(borderWidth);
118     BorderColorProperty borderColor;
119     borderColor.SetColor(theme->GetEntryBorderColor());
120     buttonNode->GetRenderContext()->UpdateBorderColor(borderColor);
121     buttonNode->MarkModifyDone();
122 
123     auto imageNode = CreateButtonImageChild(isAdd, theme);
124     CHECK_NULL_RETURN(imageNode, nullptr);
125     imageNode->MountToParent(buttonNode);
126     return buttonNode;
127 }
128 
CreateButtonImageChild(bool isAdd,const RefPtr<CalendarTheme> & theme)129 RefPtr<FrameNode> CalendarPickerModelNG::CreateButtonImageChild(bool isAdd, const RefPtr<CalendarTheme>& theme)
130 {
131     auto imageNode = FrameNode::CreateFrameNode(
132         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
133     CHECK_NULL_RETURN(imageNode, nullptr);
134     imageNode->GetLayoutProperty()->UpdateUserDefinedIdealSize(
135         CalcSize(CalcLength(theme->GetEntryArrowWidth()), CalcLength(theme->GetEntryArrowHeight())));
136     auto pipeline = PipelineBase::GetCurrentContext();
137     CHECK_NULL_RETURN(pipeline, nullptr);
138     auto iconTheme = pipeline->GetTheme<IconTheme>();
139     std::string iconPath;
140     ImageSourceInfo imageSourceInfo;
141     if (isAdd) {
142         imageSourceInfo.SetResourceId(InternalResource::ResourceId::IC_PUBLIC_ARROW_UP_SVG);
143         iconPath = iconTheme->GetIconPath(InternalResource::ResourceId::IC_PUBLIC_ARROW_UP_SVG);
144     } else {
145         imageSourceInfo.SetResourceId(InternalResource::ResourceId::IC_PUBLIC_ARROW_DOWN_SVG);
146         iconPath = iconTheme->GetIconPath(InternalResource::ResourceId::IC_PUBLIC_ARROW_DOWN_SVG);
147     }
148     imageSourceInfo.SetSrc(iconPath, theme->GetEntryArrowColor());
149     imageNode->GetLayoutProperty<ImageLayoutProperty>()->UpdateImageSourceInfo(imageSourceInfo);
150     imageNode->MarkModifyDone();
151     return imageNode;
152 }
153 
CreateButtonFlexChild(int32_t buttonFlexId,const RefPtr<CalendarTheme> & theme)154 RefPtr<FrameNode> CalendarPickerModelNG::CreateButtonFlexChild(int32_t buttonFlexId, const RefPtr<CalendarTheme>& theme)
155 {
156     auto flexNode = FrameNode::GetOrCreateFrameNode(
157         V2::COLUMN_ETS_TAG, buttonFlexId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
158     CHECK_NULL_RETURN(flexNode, nullptr);
159     auto flexLayoutProperty = flexNode->GetLayoutProperty<LinearLayoutProperty>();
160     CHECK_NULL_RETURN(flexLayoutProperty, nullptr);
161     flexLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER);
162     flexLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS);
163     return flexNode;
164 }
165 
CreateCalendarNodeChild(int32_t contentId,const CalendarSettingData & settingData,const RefPtr<CalendarTheme> & theme,TextDirection textDirection)166 RefPtr<FrameNode> CalendarPickerModelNG::CreateCalendarNodeChild(int32_t contentId,
167     const CalendarSettingData& settingData, const RefPtr<CalendarTheme>& theme, TextDirection textDirection)
168 {
169     auto contentNode = FrameNode::GetOrCreateFrameNode(
170         V2::ROW_ETS_TAG, contentId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
171     CHECK_NULL_RETURN(contentNode, nullptr);
172 
173     auto linearLayoutProperty = contentNode->GetLayoutProperty<LinearLayoutProperty>();
174     CHECK_NULL_RETURN(linearLayoutProperty, nullptr);
175 
176     linearLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER);
177     linearLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
178     contentNode->GetRenderContext()->SetClipToFrame(true);
179     linearLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
180     BorderRadiusProperty borderRadius;
181     borderRadius.radiusTopLeft = theme->GetEntryBorderRadius();
182     borderRadius.radiusBottomLeft = theme->GetEntryBorderRadius();
183     borderRadius.radiusTopRight = theme->GetEntryBorderRadius();
184     borderRadius.radiusBottomLeft = theme->GetEntryBorderRadius();
185     contentNode->GetRenderContext()->UpdateBorderRadius(borderRadius);
186     PaddingProperty padding;
187     padding.top = CalcLength(theme->GetEntryDateTopBottomMargin());
188     padding.left = CalcLength(theme->GetEntryDateLeftRightMargin());
189     padding.right = CalcLength(theme->GetEntryDateLeftRightMargin());
190     padding.bottom = CalcLength(theme->GetEntryDateTopBottomMargin());
191     linearLayoutProperty->UpdatePadding(padding);
192     linearLayoutProperty->UpdateLayoutDirection(TextDirection::LTR);
193 
194     CreateDateNode(contentId, settingData);
195     contentNode->MarkModifyDone();
196     return contentNode;
197 }
198 
CreateDateNode(int32_t contentId,const CalendarSettingData & settingData)199 void CalendarPickerModelNG::CreateDateNode(int32_t contentId, const CalendarSettingData& settingData)
200 {
201     auto contentNode = FrameNode::GetOrCreateFrameNode(
202         V2::ROW_ETS_TAG, contentId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
203     CHECK_NULL_VOID(contentNode);
204     std::map<std::size_t, std::string> order = GetDateNodeOrder(settingData);
205 
206     auto firstDateNode = CreateDateTextNode(order[0]);
207     CHECK_NULL_VOID(firstDateNode);
208     firstDateNode->MountToParent(contentNode);
209     auto textNode1 = CreateDateTextNode("/");
210     CHECK_NULL_VOID(textNode1);
211     textNode1->MountToParent(contentNode);
212     auto secondDateNode = CreateDateTextNode(order[1]);
213     CHECK_NULL_VOID(secondDateNode);
214     secondDateNode->MountToParent(contentNode);
215     auto textNode2 = CreateDateTextNode("/");
216     CHECK_NULL_VOID(textNode2);
217     textNode2->MountToParent(contentNode);
218     auto thirdDateNode = CreateDateTextNode(order[2]);
219     CHECK_NULL_VOID(thirdDateNode);
220     thirdDateNode->MountToParent(contentNode);
221 }
222 
CreateDateTextNode(const std::string & textContent)223 RefPtr<FrameNode> CalendarPickerModelNG::CreateDateTextNode(const std::string& textContent)
224 {
225     auto pipeline = PipelineBase::GetCurrentContext();
226     CHECK_NULL_RETURN(pipeline, nullptr);
227     RefPtr<CalendarTheme> calendarTheme = pipeline->GetTheme<CalendarTheme>();
228     CHECK_NULL_RETURN(calendarTheme, nullptr);
229     auto textNode = FrameNode::CreateFrameNode(
230         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
231     CHECK_NULL_RETURN(textNode, nullptr);
232     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
233     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
234     textLayoutProperty->UpdateContent(textContent);
235     textLayoutProperty->UpdateMaxLines(1);
236     textLayoutProperty->UpdateTextColor(calendarTheme->GetEntryFontColor());
237     textLayoutProperty->UpdateFontSize(calendarTheme->GetEntryFontSize());
238     textNode->MarkModifyDone();
239     return textNode;
240 }
241 
CreateNode(int32_t nodeId,const CalendarSettingData & settingData)242 RefPtr<FrameNode> CalendarPickerModelNG::CreateNode(int32_t nodeId, const CalendarSettingData& settingData)
243 {
244     auto pickerNode = FrameNode::GetOrCreateFrameNode(
245         V2::CALENDAR_PICKER_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<CalendarPickerPattern>(); });
246     auto pickerPattern = pickerNode->GetPattern<CalendarPickerPattern>();
247     CHECK_NULL_RETURN(pickerPattern, pickerNode);
248     auto pipelineContext = pickerNode->GetContext();
249     CHECK_NULL_RETURN(pipelineContext, pickerNode);
250     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
251     CHECK_NULL_RETURN(theme, pickerNode);
252     pickerPattern->SetCalendarData(settingData);
253     pickerNode->GetLayoutProperty()->UpdateUserDefinedIdealSize(
254         CalcSize(std::nullopt, CalcLength(theme->GetEntryHeight())));
255     BorderWidthProperty borderWidth;
256     borderWidth.SetBorderWidth(theme->GetEntryBorderWidth());
257     pickerNode->GetLayoutProperty()->UpdateBorderWidth(borderWidth);
258     CHECK_NULL_RETURN(pickerNode->GetRenderContext(), pickerNode);
259     BorderColorProperty borderColor;
260     borderColor.SetColor(theme->GetEntryBorderColor());
261     pickerNode->GetRenderContext()->UpdateBorderColor(borderColor);
262     BorderRadiusProperty borderRadius;
263     borderRadius.SetRadius(theme->GetEntryBorderRadius());
264     pickerNode->GetRenderContext()->UpdateBorderRadius(borderRadius);
265     pickerNode->GetRenderContext()->SetClipToFrame(true);
266     pickerNode->GetRenderContext()->SetClipToBounds(true);
267     pickerNode->GetRenderContext()->UpdateClipEdge(true);
268     CHECK_NULL_RETURN(pickerNode->GetLayoutProperty<LinearLayoutProperty>(), pickerNode);
269     pickerNode->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_START);
270     pickerNode->GetLayoutProperty<LinearLayoutProperty>()->UpdateCrossAxisAlign(FlexAlign::CENTER);
271     pickerNode->GetLayoutProperty<LinearLayoutProperty>()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
272     CalendarPickerModelNG::LayoutPicker(pickerPattern, pickerNode, settingData, theme);
273 
274     pickerNode->MarkModifyDone();
275     return pickerNode;
276 }
277 
SetEdgeAlign(const CalendarEdgeAlign & alignType,const DimensionOffset & offset)278 void CalendarPickerModelNG::SetEdgeAlign(const CalendarEdgeAlign& alignType, const DimensionOffset& offset)
279 {
280     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
281     CHECK_NULL_VOID(frameNode);
282     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
283     CHECK_NULL_VOID(pickerPattern);
284     pickerPattern->SetCalendarEdgeAlign(alignType);
285     pickerPattern->SetCalendarDialogOffset(offset);
286 
287     ACE_UPDATE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, DialogAlignType, alignType);
288     ACE_UPDATE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, DialogOffset, offset);
289 }
290 
SetTextStyle(const PickerTextStyle & textStyle)291 void CalendarPickerModelNG::SetTextStyle(const PickerTextStyle& textStyle)
292 {
293     auto pipeline = PipelineBase::GetCurrentContext();
294     CHECK_NULL_VOID(pipeline);
295     RefPtr<CalendarTheme> calendarTheme = pipeline->GetTheme<CalendarTheme>();
296     CHECK_NULL_VOID(calendarTheme);
297     if (textStyle.fontSize.has_value() && textStyle.fontSize->IsValid()) {
298         ACE_UPDATE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, FontSize, textStyle.fontSize.value());
299     } else {
300         ACE_UPDATE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, FontSize, calendarTheme->GetEntryFontSize());
301     }
302     ACE_UPDATE_LAYOUT_PROPERTY(
303         CalendarPickerLayoutProperty, Color, textStyle.textColor.value_or(calendarTheme->GetEntryFontColor()));
304     ACE_UPDATE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, Weight, textStyle.fontWeight.value_or(FontWeight::NORMAL));
305 }
306 
SetOnChange(SelectedChangeEvent && onChange)307 void CalendarPickerModelNG::SetOnChange(SelectedChangeEvent&& onChange)
308 {
309     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
310     CHECK_NULL_VOID(frameNode);
311     auto eventHub = frameNode->GetEventHub<CalendarPickerEventHub>();
312     CHECK_NULL_VOID(eventHub);
313     eventHub->SetOnChangeEvent(std::move(onChange));
314 }
315 
SetChangeEvent(SelectedChangeEvent && onChange)316 void CalendarPickerModelNG::SetChangeEvent(SelectedChangeEvent&& onChange)
317 {
318     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
319     CHECK_NULL_VOID(frameNode);
320     auto eventHub = frameNode->GetEventHub<CalendarPickerEventHub>();
321     CHECK_NULL_VOID(eventHub);
322     eventHub->SetChangeEvent(std::move(onChange));
323 }
324 
SetPadding(const PaddingProperty & padding)325 void CalendarPickerModelNG::SetPadding(const PaddingProperty& padding)
326 {
327     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
328     CHECK_NULL_VOID(frameNode);
329     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
330     CHECK_NULL_VOID(pickerPattern);
331     if (!pickerPattern->HasContentNode()) {
332         return;
333     }
334     auto contentNode = AceType::DynamicCast<FrameNode>(frameNode->GetFirstChild());
335     CHECK_NULL_VOID(contentNode);
336     auto linearLayoutProperty = contentNode->GetLayoutProperty();
337     CHECK_NULL_VOID(linearLayoutProperty);
338     linearLayoutProperty->UpdatePadding(padding);
339 }
340 
SetTextStyle(FrameNode * frameNode,const PickerTextStyle & textStyle)341 void CalendarPickerModelNG::SetTextStyle(FrameNode* frameNode, const PickerTextStyle& textStyle)
342 {
343     auto pipeline = PipelineBase::GetCurrentContextSafely();
344     CHECK_NULL_VOID(pipeline);
345     RefPtr<CalendarTheme> calendarTheme = pipeline->GetTheme<CalendarTheme>();
346     CHECK_NULL_VOID(calendarTheme);
347     if (textStyle.fontSize.has_value() && textStyle.fontSize->IsValid()) {
348         ACE_UPDATE_NODE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, FontSize, textStyle.fontSize.value(), frameNode);
349     } else {
350         ACE_UPDATE_NODE_LAYOUT_PROPERTY(
351             CalendarPickerLayoutProperty, FontSize, calendarTheme->GetEntryFontSize(), frameNode);
352     }
353     ACE_UPDATE_NODE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, Color,
354         textStyle.textColor.value_or(calendarTheme->GetEntryFontColor()), frameNode);
355     ACE_UPDATE_NODE_LAYOUT_PROPERTY(
356         CalendarPickerLayoutProperty, Weight, textStyle.fontWeight.value_or(FontWeight::NORMAL), frameNode);
357 }
358 
ClearBorderColor()359 void CalendarPickerModelNG::ClearBorderColor()
360 {
361     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
362     CHECK_NULL_VOID(frameNode);
363     auto pipelineContext = frameNode->GetContext();
364     CHECK_NULL_VOID(pipelineContext);
365     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
366     CHECK_NULL_VOID(theme);
367     BorderColorProperty borderColor;
368     borderColor.SetColor(theme->GetEntryBorderColor());
369     frameNode->GetRenderContext()->UpdateBorderColor(borderColor);
370 }
371 
ClearBorderRadius()372 void CalendarPickerModelNG::ClearBorderRadius()
373 {
374     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
375     CHECK_NULL_VOID(frameNode);
376     auto pipelineContext = frameNode->GetContext();
377     CHECK_NULL_VOID(pipelineContext);
378     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
379     CHECK_NULL_VOID(theme);
380     BorderRadiusProperty borderRadius;
381     borderRadius.SetRadius(theme->GetEntryBorderRadius());
382     frameNode->GetRenderContext()->UpdateBorderRadius(borderRadius);
383 }
384 
ClearHeight()385 void CalendarPickerModelNG::ClearHeight()
386 {
387     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
388     CHECK_NULL_VOID(frameNode);
389     auto pipelineContext = frameNode->GetContext();
390     CHECK_NULL_VOID(pipelineContext);
391     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
392     CHECK_NULL_VOID(theme);
393     frameNode->GetLayoutProperty()->UpdateUserDefinedIdealSize(
394         CalcSize(std::nullopt, CalcLength(theme->GetEntryHeight())));
395 }
396 
ClearBorder()397 void CalendarPickerModelNG::ClearBorder()
398 {
399     ClearBorderWidth();
400     ClearBorderRadius();
401     ClearBorderColor();
402 }
403 
ClearBorderWidth()404 void CalendarPickerModelNG::ClearBorderWidth()
405 {
406     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
407     CHECK_NULL_VOID(frameNode);
408     auto pipelineContext = frameNode->GetContext();
409     CHECK_NULL_VOID(pipelineContext);
410     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
411     CHECK_NULL_VOID(theme);
412     BorderWidthProperty borderWidth;
413     borderWidth.SetBorderWidth(theme->GetEntryBorderWidth());
414     frameNode->GetLayoutProperty()->UpdateBorderWidth(borderWidth);
415 }
416 
ClearPadding()417 void CalendarPickerModelNG::ClearPadding()
418 {
419     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
420     CHECK_NULL_VOID(frameNode);
421     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
422     CHECK_NULL_VOID(pickerPattern);
423     if (!pickerPattern->HasContentNode()) {
424         return;
425     }
426     auto contentNode = AceType::DynamicCast<FrameNode>(frameNode->GetFirstChild());
427     CHECK_NULL_VOID(contentNode);
428     auto linearLayoutProperty = contentNode->GetLayoutProperty();
429     CHECK_NULL_VOID(linearLayoutProperty);
430     auto pipelineContext = frameNode->GetContext();
431     CHECK_NULL_VOID(pipelineContext);
432     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
433     CHECK_NULL_VOID(theme);
434     PaddingProperty padding;
435     padding.top = CalcLength(theme->GetEntryDateTopBottomMargin());
436     padding.left = CalcLength(theme->GetEntryDateLeftRightMargin());
437     padding.right = CalcLength(theme->GetEntryDateLeftRightMargin());
438     padding.bottom = CalcLength(theme->GetEntryDateTopBottomMargin());
439     linearLayoutProperty->UpdatePadding(padding);
440 }
441 
GetCalendarTheme()442 RefPtr<CalendarTheme> GetCalendarTheme()
443 {
444     auto pipeline = PipelineBase::GetCurrentContextSafely();
445     CHECK_NULL_RETURN(pipeline, nullptr);
446     return pipeline->GetTheme<CalendarTheme>();
447 }
448 
GetTextStyle(FrameNode * frameNode)449 PickerTextStyle CalendarPickerModelNG::GetTextStyle(FrameNode* frameNode)
450 {
451     PickerTextStyle textStyle;
452     CHECK_NULL_RETURN(frameNode, textStyle);
453     auto calendarTheme = GetCalendarTheme();
454     CHECK_NULL_RETURN(calendarTheme, textStyle);
455     auto calendarPickerProperty = frameNode->GetLayoutProperty<CalendarPickerLayoutProperty>();
456     CHECK_NULL_RETURN(calendarPickerProperty, textStyle);
457     textStyle.textColor =
458         calendarPickerProperty->HasColor() ? calendarPickerProperty->GetColor() : calendarTheme->GetEntryFontColor();
459     textStyle.fontSize = calendarPickerProperty->HasFontSize() ? calendarPickerProperty->GetFontSize()
460                                                                : calendarTheme->GetEntryFontSize();
461     textStyle.fontWeight =
462         calendarPickerProperty->HasWeight() ? calendarPickerProperty->GetWeight() : FontWeight::NORMAL;
463     return textStyle;
464 }
465 
GetEdgeAlignType(FrameNode * frameNode)466 CalendarEdgeAlign CalendarPickerModelNG::GetEdgeAlignType(FrameNode* frameNode)
467 {
468     CHECK_NULL_RETURN(frameNode, CalendarEdgeAlign::EDGE_ALIGN_END);
469     auto layoutProperty = frameNode->GetLayoutProperty<CalendarPickerLayoutProperty>();
470     CHECK_NULL_RETURN(layoutProperty, CalendarEdgeAlign::EDGE_ALIGN_END);
471     return layoutProperty->GetDialogAlignType().value_or(CalendarEdgeAlign::EDGE_ALIGN_END);
472 }
473 
GetEdgeOffset(FrameNode * frameNode)474 DimensionOffset CalendarPickerModelNG::GetEdgeOffset(FrameNode* frameNode)
475 {
476     DimensionOffset offsetDimension(0.0_vp, 0.0_vp);
477     CHECK_NULL_RETURN(frameNode, offsetDimension);
478     auto layoutProperty = frameNode->GetLayoutProperty<CalendarPickerLayoutProperty>();
479     CHECK_NULL_RETURN(layoutProperty, offsetDimension);
480     return layoutProperty->GetDialogOffset().value_or(offsetDimension);
481 }
482 
SetEdgeAlign(FrameNode * frameNode,const CalendarEdgeAlign & alignType,const DimensionOffset & offset)483 void CalendarPickerModelNG::SetEdgeAlign(
484     FrameNode* frameNode, const CalendarEdgeAlign& alignType, const DimensionOffset& offset)
485 {
486     auto layoutProperty = frameNode->GetLayoutProperty<CalendarPickerLayoutProperty>();
487     CHECK_NULL_VOID(layoutProperty);
488     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
489     CHECK_NULL_VOID(pickerPattern);
490     pickerPattern->SetCalendarEdgeAlign(alignType);
491     pickerPattern->SetCalendarDialogOffset(offset);
492 
493     ACE_UPDATE_NODE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, DialogAlignType, alignType, frameNode);
494     ACE_UPDATE_NODE_LAYOUT_PROPERTY(CalendarPickerLayoutProperty, DialogOffset, offset, frameNode);
495 }
496 
SetPadding(FrameNode * frameNode,const PaddingProperty & padding)497 void CalendarPickerModelNG::SetPadding(FrameNode* frameNode, const PaddingProperty& padding)
498 {
499     CHECK_NULL_VOID(frameNode);
500     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
501     CHECK_NULL_VOID(pickerPattern);
502     if (!pickerPattern->HasContentNode()) {
503         return;
504     }
505     auto contentNode = AceType::DynamicCast<FrameNode>(frameNode->GetFirstChild());
506     CHECK_NULL_VOID(contentNode);
507     auto linearLayoutProperty = contentNode->GetLayoutProperty();
508     CHECK_NULL_VOID(linearLayoutProperty);
509     linearLayoutProperty->UpdatePadding(padding);
510 }
511 
ClearPadding(FrameNode * frameNode)512 void CalendarPickerModelNG::ClearPadding(FrameNode* frameNode)
513 {
514     CHECK_NULL_VOID(frameNode);
515     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
516     CHECK_NULL_VOID(pickerPattern);
517     if (!pickerPattern->HasContentNode()) {
518         return;
519     }
520     auto contentNode = AceType::DynamicCast<FrameNode>(frameNode->GetFirstChild());
521     CHECK_NULL_VOID(contentNode);
522     auto linearLayoutProperty = contentNode->GetLayoutProperty();
523     CHECK_NULL_VOID(linearLayoutProperty);
524     auto pipelineContext = frameNode->GetContext();
525     CHECK_NULL_VOID(pipelineContext);
526     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
527     CHECK_NULL_VOID(theme);
528     PaddingProperty padding;
529     padding.top = CalcLength(theme->GetEntryDateTopBottomMargin());
530     padding.left = CalcLength(theme->GetEntryDateLeftRightMargin());
531     padding.right = CalcLength(theme->GetEntryDateLeftRightMargin());
532     padding.bottom = CalcLength(theme->GetEntryDateTopBottomMargin());
533     linearLayoutProperty->UpdatePadding(padding);
534 }
535 
ClearHeight(FrameNode * frameNode)536 void CalendarPickerModelNG::ClearHeight(FrameNode* frameNode)
537 {
538     CHECK_NULL_VOID(frameNode);
539     auto pipelineContext = frameNode->GetContext();
540     CHECK_NULL_VOID(pipelineContext);
541     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
542     CHECK_NULL_VOID(theme);
543     ViewAbstract::SetHeight(frameNode, CalcLength(theme->GetEntryHeight()));
544 }
545 
ClearBorderColor(FrameNode * frameNode)546 void CalendarPickerModelNG::ClearBorderColor(FrameNode* frameNode)
547 {
548     CHECK_NULL_VOID(frameNode);
549     auto pipelineContext = frameNode->GetContext();
550     CHECK_NULL_VOID(pipelineContext);
551     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
552     CHECK_NULL_VOID(theme);
553     BorderColorProperty borderColor;
554     borderColor.SetColor(theme->GetEntryBorderColor());
555     frameNode->GetRenderContext()->UpdateBorderColor(borderColor);
556 }
557 
ClearBorderRadius(FrameNode * frameNode)558 void CalendarPickerModelNG::ClearBorderRadius(FrameNode* frameNode)
559 {
560     CHECK_NULL_VOID(frameNode);
561     auto pipelineContext = frameNode->GetContext();
562     CHECK_NULL_VOID(pipelineContext);
563     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
564     CHECK_NULL_VOID(theme);
565     BorderRadiusProperty borderRadius;
566     borderRadius.SetRadius(theme->GetEntryBorderRadius());
567     frameNode->GetRenderContext()->UpdateBorderRadius(borderRadius);
568 }
569 
ClearBorderWidth(FrameNode * frameNode)570 void CalendarPickerModelNG::ClearBorderWidth(FrameNode* frameNode)
571 {
572     CHECK_NULL_VOID(frameNode);
573     auto pipelineContext = frameNode->GetContext();
574     CHECK_NULL_VOID(pipelineContext);
575     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
576     CHECK_NULL_VOID(theme);
577     BorderWidthProperty borderWidth;
578     borderWidth.SetBorderWidth(theme->GetEntryBorderWidth());
579     frameNode->GetLayoutProperty()->UpdateBorderWidth(borderWidth);
580 }
581 
SetHintRadiusWithNode(FrameNode * frameNode,Dimension & radius)582 void CalendarPickerModelNG::SetHintRadiusWithNode(FrameNode* frameNode, Dimension& radius)
583 {
584     CHECK_NULL_VOID(frameNode);
585     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
586     CHECK_NULL_VOID(pickerPattern);
587     auto calendarDate = pickerPattern->GetCalendarData();
588     calendarDate.dayRadius = radius;
589     pickerPattern->SetCalendarData(calendarDate);
590 }
591 
SetSelectDateWithNode(FrameNode * frameNode,uint32_t year,uint32_t month,uint32_t day)592 void CalendarPickerModelNG::SetSelectDateWithNode(FrameNode* frameNode, uint32_t year, uint32_t month, uint32_t day)
593 {
594     CHECK_NULL_VOID(frameNode);
595     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
596     CHECK_NULL_VOID(pickerPattern);
597     auto calendarDate = pickerPattern->GetCalendarData();
598     if (year > 0) {
599         calendarDate.selectedDate.SetYear(year);
600         auto yearNode = CalendarPickerModelNG::GetYearNode(frameNode);
601         if (yearNode) {
602             auto textLayoutProperty = yearNode->GetLayoutProperty<TextLayoutProperty>();
603             if (textLayoutProperty) {
604                 textLayoutProperty->UpdateContent(std::to_string(year));
605                 yearNode->MarkModifyDone();
606                 yearNode->MarkDirtyNode();
607             }
608         }
609     }
610     if (month > 0) {
611         calendarDate.selectedDate.SetMonth(month);
612         auto monthNode = CalendarPickerModelNG::GetMonthNode(frameNode);
613         if (monthNode) {
614             auto textLayoutProperty = monthNode->GetLayoutProperty<TextLayoutProperty>();
615             if (textLayoutProperty) {
616                 auto selectedMonthStr = (month < ONE_DIGIT_BOUNDARY  ? "0" : "") + std::to_string(month);
617                 textLayoutProperty->UpdateContent(selectedMonthStr);
618                 monthNode->MarkModifyDone();
619                 monthNode->MarkDirtyNode();
620             }
621         }
622     }
623     if (day > 0) {
624         calendarDate.selectedDate.SetDay(day);
625         auto dayNode = CalendarPickerModelNG::GetDayNode(frameNode);
626         if (dayNode) {
627             auto textLayoutProperty = dayNode->GetLayoutProperty<TextLayoutProperty>();
628             if (textLayoutProperty) {
629                 auto selectedDayStr = (day < ONE_DIGIT_BOUNDARY  ? "0" : "") + std::to_string(day);
630                 textLayoutProperty->UpdateContent(selectedDayStr);
631                 dayNode->MarkModifyDone();
632                 dayNode->MarkDirtyNode();
633             }
634         }
635     }
636     pickerPattern->SetCalendarData(calendarDate);
637 }
638 
GetYearNode(FrameNode * calendarPickerNode)639 RefPtr<FrameNode> CalendarPickerModelNG::GetYearNode(FrameNode* calendarPickerNode)
640 {
641     CHECK_NULL_RETURN(calendarPickerNode, nullptr);
642     auto feedbackNode = calendarPickerNode->GetFirstChild();
643     CHECK_NULL_RETURN(feedbackNode, nullptr);
644     return AceType::DynamicCast<FrameNode>(feedbackNode->GetChildAtIndex(yearNodeIndex_));
645 }
646 
GetMonthNode(FrameNode * calendarPickerNode)647 RefPtr<FrameNode> CalendarPickerModelNG::GetMonthNode(FrameNode* calendarPickerNode)
648 {
649     CHECK_NULL_RETURN(calendarPickerNode, nullptr);
650     auto feedbackNode = calendarPickerNode->GetFirstChild();
651     CHECK_NULL_RETURN(feedbackNode, nullptr);
652     return AceType::DynamicCast<FrameNode>(feedbackNode->GetChildAtIndex(monthNodeIndex_));
653 }
654 
GetDayNode(FrameNode * calendarPickerNode)655 RefPtr<FrameNode> CalendarPickerModelNG::GetDayNode(FrameNode* calendarPickerNode)
656 {
657     CHECK_NULL_RETURN(calendarPickerNode, nullptr);
658     auto feedbackNode = calendarPickerNode->GetFirstChild();
659     CHECK_NULL_RETURN(feedbackNode, nullptr);
660     return AceType::DynamicCast<FrameNode>(feedbackNode->GetChildAtIndex(dayNodeIndex_));
661 }
662 
GetHintRadius(FrameNode * frameNode)663 Dimension CalendarPickerModelNG::GetHintRadius(FrameNode* frameNode)
664 {
665     Dimension defaultRadius(DEFAULT_HINT_RADIUS);
666     CHECK_NULL_RETURN(frameNode, defaultRadius);
667     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
668     CHECK_NULL_RETURN(pickerPattern, defaultRadius);
669     auto calendarDate = pickerPattern->GetCalendarData();
670     return calendarDate.dayRadius.value_or(defaultRadius);
671 }
672 
GetSelectDateWithNode(FrameNode * frameNode)673 PickerDate CalendarPickerModelNG::GetSelectDateWithNode(FrameNode* frameNode)
674 {
675     auto defaultSelectedDate = PickerDate::Current();
676     CHECK_NULL_RETURN(frameNode, defaultSelectedDate);
677     auto pickerPattern = frameNode->GetPattern<CalendarPickerPattern>();
678     CHECK_NULL_RETURN(pickerPattern, defaultSelectedDate);
679     return pickerPattern->GetCalendarData().selectedDate;
680 }
681 
SetOnChangeWithNode(FrameNode * frameNode,SelectedChangeEvent && onChange)682 void CalendarPickerModelNG::SetOnChangeWithNode(FrameNode* frameNode, SelectedChangeEvent&& onChange)
683 {
684     CHECK_NULL_VOID(frameNode);
685     auto eventHub = frameNode->GetEventHub<CalendarPickerEventHub>();
686     CHECK_NULL_VOID(eventHub);
687     eventHub->SetOnChangeEvent(std::move(onChange));
688 }
689 
GetDateNodeOrder(const CalendarSettingData & settingData)690 std::map<std::size_t, std::string> CalendarPickerModelNG::GetDateNodeOrder(const CalendarSettingData& settingData)
691 {
692     PickerDate date = settingData.selectedDate;
693     std::vector<std::string> outOrder;
694     bool result = Localization::GetInstance()->GetDateOrder(outOrder);
695     std::map<std::size_t, std::string> order;
696     if (!result || outOrder.size() < DATE_NODE_COUNT) {
697         yearNodeIndex_ = YEAR_NODE_INDEX;
698         monthNodeIndex_ = MONTH_NODE_INDEX;
699         dayNodeIndex_ = DAY_NODE_INDEX;
700         auto num = 0;
701         order[num++] = std::to_string(date.GetYear());
702         order[num++] = (date.GetMonth() < ONE_DIGIT_BOUNDARY ? "0" : "") + std::to_string(date.GetMonth());
703         order[num] = (date.GetDay() < ONE_DIGIT_BOUNDARY ? "0" : "") + std::to_string(date.GetDay());
704     } else {
705         size_t index = 0;
706         for (size_t i = 0; i < outOrder.size(); ++i) {
707             if (outOrder[i] == "year") {
708                 yearNodeIndex_ = static_cast<int32_t>(i + index);
709                 order[i] = std::to_string(date.GetYear());
710             }
711             if (outOrder[i] == "month") {
712                 monthNodeIndex_ = static_cast<int32_t>(i + index);
713                 order[i] = (date.GetMonth() < ONE_DIGIT_BOUNDARY ? "0" : "") + std::to_string(date.GetMonth());
714             }
715             if (outOrder[i] == "day") {
716                 dayNodeIndex_ = static_cast<int32_t>(i + index);
717                 order[i] = (date.GetDay() < ONE_DIGIT_BOUNDARY ? "0" : "") + std::to_string(date.GetDay());
718             }
719             index++;
720         }
721     }
722 
723     return order;
724 }
725 } // namespace OHOS::Ace::NG
726