• 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 "core/components/picker/render_picker_base.h"
17 #include "core/components/picker/picker_date_component.h"
18 
19 #include <numeric>
20 
21 #include "base/log/event_report.h"
22 #include "core/components/picker/picker_time_component.h"
23 #include "core/event/ace_event_helper.h"
24 
25 namespace OHOS::Ace {
26 
TouchTest(const Point & globalPoint,const Point & parentLocalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result)27 bool RenderPickerBase::TouchTest(const Point& globalPoint, const Point& parentLocalPoint,
28     const TouchRestrict& touchRestrict, TouchTestResult& result)
29 {
30     if (triangle_) {
31         Rect rect(triangle_->GetGlobalOffset(), triangle_->GetLayoutSize());
32         if (rect.IsInRegion(globalPoint) && GetDisableTouchEvent()) {
33             triangle_->OnTouchTestHit(Offset(), touchRestrict, result);
34             return true;
35         }
36     }
37 
38     if (lunarText_) {
39         Rect rect(lunarText_->GetGlobalOffset(), lunarText_->GetLayoutSize());
40         if (rect.IsInRegion(globalPoint) && switch_ && switch_->GetParent().Upgrade()) {
41             return onChildTouchTest(switch_, touchRestrict, result);
42         }
43     }
44 
45     if (data_->GetSubsidiary()) {
46         if (ok_) {
47             Rect rect(ok_->GetGlobalOffset(), ok_->GetLayoutSize());
48             if (rect.IsInRegion(globalPoint) && ok_->GetParent().Upgrade()) {
49                 return onChildTouchTest(ok_, touchRestrict, result);
50             }
51         }
52 
53         if (cancel_) {
54             Rect rect(cancel_->GetGlobalOffset(), cancel_->GetLayoutSize());
55             if (rect.IsInRegion(globalPoint) && cancel_->GetParent().Upgrade()) {
56                 return onChildTouchTest(cancel_, touchRestrict, result);
57             }
58         }
59 
60         if (columnParent_) {
61             Rect rect(columnParent_->GetGlobalOffset(), columnParent_->GetLayoutSize());
62             if (!rect.IsInRegion(globalPoint)) {
63                 return false;
64             }
65         }
66     }
67 
68     return RenderNode::TouchTest(globalPoint, parentLocalPoint, touchRestrict, result);
69 }
70 
onChildTouchTest(const RefPtr<RenderNode> & child,const TouchRestrict & touchRestrict,TouchTestResult & result)71 bool RenderPickerBase::onChildTouchTest(
72     const RefPtr<RenderNode>& child, const TouchRestrict& touchRestrict, TouchTestResult& result)
73 {
74     auto parent = child->GetParent().Upgrade();
75     Point global;
76     Point local;
77     auto size = child->GetLayoutSize();
78     global = global + child->GetGlobalOffset() + Offset(size.Width() / 2.0, size.Height() / 2.0);
79     local = global - parent->GetGlobalOffset();
80     return child->TouchTest(global, local, touchRestrict, result);
81 }
82 
Update(const RefPtr<Component> & component)83 void RenderPickerBase::Update(const RefPtr<Component>& component)
84 {
85     auto picker = AceType::DynamicCast<PickerBaseComponent>(component);
86     if (!picker) {
87         LOGE("input component is incorrect type or null.");
88         EventReport::SendRenderException(RenderExcepType::RENDER_COMPONENT_ERR);
89         return;
90     }
91 
92     auto textPicker = AceType::DynamicCast<PickerTextComponent>(component);
93     if (textPicker) {
94         selectedIndex_ = textPicker->GetSelected();
95         range_ = textPicker->GetRange();
96     }
97 
98     auto time = AceType::DynamicCast<PickerTimeComponent>(component);
99     if (time) {
100         type_ = "DatePickerType.Time";
101     } else {
102         type_ = "DatePickerType.Date";
103     }
104 
105     auto datePicker = AceType::DynamicCast<PickerDateComponent>(component);
106     if (datePicker) {
107         startDateSolar_ = datePicker->GetStartDate();
108         endDateSolar_ = datePicker->GetEndDate();
109         selectedDate_ = datePicker->GetSelectedDate();
110     }
111 
112     columnHeight_ = picker->GetColumnHeight();
113     data_ = picker;
114     SetInterceptTouchEvent(!data_->GetSubsidiary());
115     data_->OnColumnsCreating();
116     onCancelCallback_ = AceAsyncEvent<void()>::Create(data_->GetOnCancel(), context_);
117     onJSChangeCallback_ = AceAsyncEvent<void(const std::string&)>::Create(data_->GetOnChange(), context_);
118     onChangeCallback_ = AceSyncEvent<void(const std::shared_ptr<BaseEventInfo>&)>::
119         Create(data_->GetOnChange(), context_);
120     onColumnChangeCallback_ = AceAsyncEvent<void(const std::string&)>::Create(data_->GetOnColumnChange(), context_);
121     onDialogAccept_ = AceAsyncEvent<void(const std::string&)>::Create(data_->GetDialogAcceptEvent(), context_);
122     onDialogCancel_ = AceAsyncEvent<void()>::Create(data_->GetDialogCancelEvent(), context_);
123     onDialogChange_ = AceAsyncEvent<void(const std::string&)>::Create(data_->GetDialogChangeEvent(), context_);
124 
125     const auto context = context_.Upgrade();
126     if (context && context->GetIsDeclarative()) {
127         if (picker->GetOnTextCancel()) {
128             onTextCancel_ = *picker->GetOnTextCancel();
129         }
130         if (picker->GetOnTextAccept()) {
131             onTextAccept_ = *picker->GetOnTextAccept();
132         }
133         if (picker->GetOnTextChange()) {
134             onTextChange_ = *picker->GetOnTextChange();
135         }
136     }
137 
138     data_->SetFinishCallback([weak = WeakClaim(this)](bool success) {
139         auto refPtr = weak.Upgrade();
140         if (refPtr) {
141             refPtr->HandleFinish(success);
142         }
143     });
144     data_->SetChangeCallback([weak = WeakClaim(this)](const std::string& tag, bool add, uint32_t index, bool notify) {
145         auto refPtr = weak.Upgrade();
146         if (refPtr) {
147             refPtr->HandleColumnChange(tag, add, index, notify);
148         }
149     });
150     if (data_->GetIsDialog() || data_->GetIsCreateDialogComponent()) {
151         SetButtonHandler();
152     }
153     SetTextDirection(data_->GetTextDirection());
154     MarkNeedLayout();
155 
156     const auto& rotationController = picker->GetRotationController();
157     if (rotationController) {
158         auto weak = AceType::WeakClaim(this);
159         rotationController->SetRequestRotationImpl(weak, context_);
160     }
161 }
162 
SetButtonHandler()163 void RenderPickerBase::SetButtonHandler()
164 {
165     // RenderPicker may created for same component(when showing again),
166     // these event id may already bind, so remove first.
167     BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(data_->GetOnCancelClickId());
168     BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(data_->GetOnOkClickId());
169 
170     auto context = context_.Upgrade();
171     if (context->GetIsDeclarative()) {
172         BackEndEventManager<void(const ClickInfo& info)>::GetInstance().BindBackendEvent(
173             data_->GetOnCancelClickId(), [weak = WeakClaim(this)](const ClickInfo& info) {
174                 const auto& picker = weak.Upgrade();
175                 if (picker) {
176                     picker->HandleFinish(false);
177                 } else {
178                     LOGE("GetOnCancelClickId picker weak.Upgrade is null");
179                 }
180             });
181         BackEndEventManager<void(const ClickInfo& info)>::GetInstance().BindBackendEvent(
182             data_->GetOnOkClickId(), [weak = WeakClaim(this)](const ClickInfo& info) {
183                 const auto& picker = weak.Upgrade();
184                 if (picker) {
185                     picker->HandleFinish(true);
186                 } else {
187                     LOGE("GetOnOkClickId picker weak.Upgrade is null");
188                 }
189             });
190     } else {
191         BackEndEventManager<void()>::GetInstance().BindBackendEvent(
192             data_->GetOnCancelClickId(), [weak = WeakClaim(this)]() {
193                 const auto& picker = weak.Upgrade();
194                 if (picker) {
195                     picker->HandleFinish(false);
196                 } else {
197                     LOGE("GetOnCancelClickId picker weak.Upgrade is null");
198                 }
199             });
200         BackEndEventManager<void()>::GetInstance().BindBackendEvent(
201             data_->GetOnOkClickId(), [weak = WeakClaim(this)]() {
202                 const auto& picker = weak.Upgrade();
203                 if (picker) {
204                     picker->HandleFinish(true);
205                 } else {
206                     LOGE("GetOnOkClickId picker weak.Upgrade is null");
207                 }
208             });
209     }
210     auto cancelNode = data_->GetCancelAccessibility();
211     if (cancelNode) {
212         cancelNode->SetActionClickImpl([weakPtr = WeakClaim(this)]() {
213             const auto& picker = weakPtr.Upgrade();
214             if (picker) {
215                 picker->HandleFinish(false);
216             }
217         });
218     }
219     auto okNode = data_->GetOkAccessibility();
220     if (okNode) {
221         okNode->SetActionClickImpl([weakPtr = WeakClaim(this)]() {
222             const auto& picker = weakPtr.Upgrade();
223             if (picker) {
224                 picker->HandleFinish(true);
225             }
226         });
227     }
228 }
229 
HandleTriangleClick(bool value)230 void RenderPickerBase::HandleTriangleClick(bool value)
231 {
232     if (!data_) {
233         LOGE("data is null");
234         return;
235     }
236 
237     data_->OnTriangleCallback(value);
238     MarkNeedRender();
239 }
240 
SetTriangleHandler()241 void RenderPickerBase::SetTriangleHandler()
242 {
243     if (!triangle_ || triangle_->GetOnClick()) {
244         return;
245     }
246 
247     triangle_->SetOnClick([weak = WeakClaim(this)](bool value) {
248         auto refPtr = weak.Upgrade();
249         if (!refPtr) {
250             return;
251         }
252         refPtr->HandleTriangleClick(value);
253     });
254 }
255 
SetSwitchHandler()256 void RenderPickerBase::SetSwitchHandler()
257 {
258     if (switchHandlerSetted_) {
259         return;
260     }
261 
262     if (!switch_) {
263         LOGE("can not get switch button.");
264         return;
265     }
266 
267     auto switchNode = data_->GetSwitchAccessibility();
268     switch_->SetOnChange([weak = WeakClaim(this)](bool value) {
269         auto refPtr = weak.Upgrade();
270         if (!refPtr) {
271             return;
272         }
273         refPtr->HandleSwitch(value);
274         if (!refPtr->data_) {
275             return;
276         }
277         auto node = refPtr->data_->GetSwitchAccessibility();
278         auto pipeline = refPtr->context_.Upgrade();
279         if (node && pipeline && node->GetClicked()) {
280             node->SetClicked(false);
281             AccessibilityEvent clickEvent;
282             clickEvent.nodeId = node->GetNodeId();
283             clickEvent.eventType = "click";
284             pipeline->SendEventToAccessibility(clickEvent);
285         }
286     });
287 
288     if (switchNode && switch_) {
289         switchNode->SetActionClickImpl([weak = WeakClaim(this)]() {
290             auto refPtr = weak.Upgrade();
291             if (refPtr && refPtr->switch_) {
292                 refPtr->switch_->HandleClick();
293             }
294         });
295     }
296     switchHandlerSetted_ = true;
297 }
298 
PerformLayout()299 void RenderPickerBase::PerformLayout()
300 {
301     SetSwitchHandler();
302     SetTriangleHandler();
303 
304     if (!data_ || !outBox_) {
305         LOGE("data or out box is null.");
306         return;
307     }
308 
309     if (data_->GetIsDialog()) {
310         LayoutBoxes();
311         LayoutColumns();
312         SetLayoutSize(GetLayoutParam().GetMaxSize());
313         if (!hasLayout_) {
314             hasLayout_ = true;
315         }
316         return;
317     }
318 
319     double lunarHeight = 16.0; // use 16.0 not 0.0 for default
320     if (data_->GetHasLunar() && data_->GetTheme()) {
321         auto theme = data_->GetTheme();
322         lunarHeight = NormalizeToPx(theme->GetButtonTopPadding()) + NormalizeToPx(theme->GetLunarHeight());
323     }
324     for (const auto& column : columns_) {
325         column->SetAdjustHeight(lunarHeight);
326     }
327     outBox_->Layout(GetLayoutParam());
328     LayoutColumns();
329     SetLayoutSize(outBox_->GetLayoutSize());
330 }
331 
LayoutBoxes()332 void RenderPickerBase::LayoutBoxes()
333 {
334     if (!stack_ || !outBox_ || !box_ || !data_ || !data_->GetTheme()) {
335         LOGE("inner param invalidate.");
336         return;
337     }
338     auto theme = data_->GetTheme();
339     outBox_->Layout(LayoutParam());
340     SetOutBoxBorderRadius();
341     Size innerSize = box_->GetLayoutSize();
342     if (innerSize.Width() < NormalizeToPx(theme->GetButtonWidth()) * 2.0) { // ok width + cancel width
343         innerSize.SetWidth(NormalizeToPx(theme->GetButtonWidth()) * 2.0);   // ok width + cancel width
344     }
345     // the min size of pupup screen interval is 12.0 vp + 12.0 vp = 24.0 vp
346     if (innerSize.Width() + NormalizeToPx(24.0_vp) > stack_->GetLayoutSize().Width()) {
347         innerSize.SetWidth(stack_->GetLayoutSize().Width() - NormalizeToPx(24.0_vp));
348     }
349     LayoutParam layout;
350     layout.SetFixedSize(GetLayoutParam().GetMaxSize());
351     outBox_->Layout(layout);
352     double x = (outBox_->GetLayoutSize().Width() - innerSize.Width()) / 2.0; // place center
353     double y = 0.0;
354     auto deviceType = SystemProperties::GetDeviceType();
355     if (theme->GetShowButtons() && deviceType == DeviceType::PHONE) {
356         y = (outBox_->GetLayoutSize().Height() - innerSize.Height() -
357              NormalizeToPx(theme->GetButtonTopPadding())); // place bottom
358     } else {
359         y = (outBox_->GetLayoutSize().Height() - innerSize.Height()) / 2.0; // place center
360     }
361     box_->SetPosition(Offset(x, y));
362     layout.SetFixedSize(innerSize);
363     box_->Layout(layout);
364     if (data_->GetSubsidiary()) {
365         auto adjustHeight = NormalizeToPx(theme->GetColumnBottomTotalHeight(data_->GetMasterHasLunar()));
366         y -= adjustHeight;
367         auto outerSize = innerSize;
368         outerSize.AddHeight(adjustHeight);
369         layout.SetFixedSize(outerSize);
370         outBox_->SetPosition(Offset(x, y));
371         outBox_->Layout(layout);
372         double boxY = NormalizeToPx(theme->GetButtonHeight() + theme->GetButtonTopPadding());
373         if (data_->GetMasterHasLunar()) {
374             boxY += NormalizeToPx(theme->GetLunarHeight() + theme->GetButtonTopPadding());
375         }
376         box_->SetPosition(Offset(0.0, boxY));
377         layout.SetFixedSize(innerSize);
378         box_->Layout(layout);
379     }
380 }
381 
LayoutColumns()382 void RenderPickerBase::LayoutColumns()
383 {
384     if (!columnParent_ || columns_.empty() || !data_) {
385         LOGE("inner param invalidate.");
386         return;
387     }
388 
389     double totalWidth = columnParent_->GetLayoutSize().Width();
390     double totalHeight = columnParent_->GetLayoutSize().Height();
391     int32_t ratioCount = std::accumulate(columns_.begin(), columns_.end(), 0,
392         [](uint32_t sum, const RefPtr<RenderPickerColumn>& column) { return sum += column->GetWidthRatio(); });
393 
394     bool divideEvenly = SystemProperties::GetDeviceType() != DeviceType::PHONE || ratioCount == 0;
395     double oneWidth = divideEvenly ? totalWidth / columns_.size() : totalWidth / ratioCount;
396     double left = 0;
397     LayoutParam layout;
398     for (uint32_t index = 0; index < columns_.size(); ++index) {
399         uint32_t realIndex = 0;
400         if (data_->NeedRtlColumnOrder()) {
401             if (data_->GetTextDirection() == TextDirection::RTL) {
402                 realIndex = columns_.size() - 1 - index; // the last index is columns_.size() - 1
403             } else {
404                 realIndex = index;
405             }
406         } else {
407             realIndex = index;
408         }
409         columns_[realIndex]->SetPosition(Offset(left + columns_[realIndex]->GetXOffset(), 0.0));
410         double columnWidth = divideEvenly ? oneWidth : oneWidth * columns_[realIndex]->GetWidthRatio();
411         layout.SetFixedSize(Size(columnWidth, totalHeight));
412         columns_[realIndex]->Layout(layout);
413         left += columnWidth;
414     }
415 }
416 
SetOutBoxBorderRadius()417 void RenderPickerBase::SetOutBoxBorderRadius()
418 {
419     auto context = context_.Upgrade();
420     if (context && context->GetIsDeclarative()) {
421         auto decoration = outBox_->GetBackDecoration();
422         auto parent = outBox_->GetParent().Upgrade();
423         auto borderRadius = Radius();
424         while (parent) {
425             if (AceType::InstanceOf<RenderBox>(parent)) {
426                 auto boxParent = DynamicCast<RenderBox>(parent);
427                 borderRadius = boxParent->GetBackDecoration()->GetBorder().TopLeftRadius();
428                 break;
429             }
430             parent = parent->GetParent().Upgrade();
431         }
432         decoration->SetBorderRadius(borderRadius);
433         outBox_->SetBackDecoration(decoration);
434     }
435 }
436 
UpdateAccessibility()437 void RenderPickerBase::UpdateAccessibility()
438 {
439     if (!data_) {
440         LOGE("inner params of render picker base has error.");
441         return;
442     }
443 
444     auto titleNode = data_->GetTitleAccessibility();
445     if (titleNode && title_) {
446         UpdateTextAccessibility(titleNode, title_);
447     }
448 
449     auto lunarNode = data_->GetLunarAccessibility();
450     if (lunarNode && lunarText_) {
451         UpdateTextAccessibility(lunarNode, lunarText_);
452     }
453 
454     auto switchNode = data_->GetSwitchAccessibility();
455     if (switchNode && switch_) {
456         UpdateSwitchAccessibility(switchNode, switch_);
457     }
458 
459     auto cancelNode = data_->GetCancelAccessibility();
460     if (cancelNode && cancel_) {
461         UpdateButtonAccessibility(cancelNode, cancel_);
462     }
463 
464     auto okNode = data_->GetOkAccessibility();
465     if (okNode && ok_) {
466         UpdateButtonAccessibility(okNode, ok_);
467     }
468 
469 #if defined(PREVIEW)
470     auto pickerDialogNode = data_->GetPickerDialogAccessibility();
471     if (pickerDialogNode && box_) {
472         UpdatePickerDialogAccessibility(pickerDialogNode, box_);
473     }
474 #endif
475 }
476 
UpdateSwitchAccessibility(const RefPtr<AccessibilityNode> & node,const RefPtr<RenderCheckbox> & renderSwitch)477 void RenderPickerBase::UpdateSwitchAccessibility(
478     const RefPtr<AccessibilityNode>& node, const RefPtr<RenderCheckbox>& renderSwitch)
479 {
480     if (!node || !renderSwitch) {
481         return;
482     }
483     auto pipeline = context_.Upgrade();
484     if (!pipeline) {
485         return;
486     }
487     auto viewScale = pipeline->GetViewScale();
488     auto leftTop = renderSwitch->GetGlobalOffset();
489     node->SetLeft(leftTop.GetX() * viewScale);
490     node->SetTop(leftTop.GetY() * viewScale);
491     auto size = renderSwitch->GetLayoutSize();
492     node->SetWidth(size.Width() * viewScale);
493     node->SetHeight(size.Height() * viewScale);
494     node->SetCheckedState(renderSwitch->GetChecked());
495     if (lunarText_) {
496         node->SetText(lunarText_->GetTextData());
497     }
498     node->SetEnabledState(true);
499     node->SetCheckableState(true);
500     node->SetClickableState(true);
501     node->SetFocusableState(true);
502     node->AddSupportAction(AceAction::ACTION_CLICK);
503 }
504 
UpdatePickerDialogAccessibility(const RefPtr<AccessibilityNode> & node,const RefPtr<RenderBox> & box)505 void RenderPickerBase::UpdatePickerDialogAccessibility(
506     const RefPtr<AccessibilityNode>& node, const RefPtr<RenderBox>& box)
507 {
508     if (!node || !box) {
509         return;
510     }
511     auto pipeline = context_.Upgrade();
512     if (!pipeline) {
513         return;
514     }
515     auto viewScale = pipeline->GetViewScale();
516     auto leftTop = box->GetGlobalOffset();
517     node->SetLeft(leftTop.GetX() * viewScale);
518     node->SetTop(leftTop.GetY() * viewScale);
519     auto size = box->GetLayoutSize();
520     node->SetWidth(size.Width() * viewScale);
521     node->SetHeight(size.Height() * viewScale);
522 }
523 
UpdateTextAccessibility(const RefPtr<AccessibilityNode> & node,const RefPtr<RenderText> & text)524 void RenderPickerBase::UpdateTextAccessibility(const RefPtr<AccessibilityNode>& node, const RefPtr<RenderText>& text)
525 {
526     if (!node || !text) {
527         return;
528     }
529     auto pipeline = context_.Upgrade();
530     if (!pipeline) {
531         return;
532     }
533     auto viewScale = pipeline->GetViewScale();
534     auto leftTop = text->GetGlobalOffset();
535     node->SetLeft(leftTop.GetX() * viewScale);
536     node->SetTop(leftTop.GetY() * viewScale);
537     auto size = text->GetLayoutSize();
538     node->SetWidth(size.Width() * viewScale);
539     node->SetHeight(size.Height() * viewScale);
540     node->SetText(text->GetTextData());
541 }
542 
UpdateButtonAccessibility(const RefPtr<AccessibilityNode> & node,const RefPtr<RenderButton> & button)543 void RenderPickerBase::UpdateButtonAccessibility(
544     const RefPtr<AccessibilityNode>& node, const RefPtr<RenderButton>& button)
545 {
546     if (!node || !button) {
547         return;
548     }
549     auto pipeline = context_.Upgrade();
550     if (!pipeline) {
551         return;
552     }
553     auto viewScale = pipeline->GetViewScale();
554     auto leftTop = button->GetGlobalOffset();
555     node->SetLeft(leftTop.GetX() * viewScale);
556     node->SetTop(leftTop.GetY() * viewScale);
557     auto size = button->GetLayoutSize();
558     node->SetWidth(size.Width() * viewScale);
559     node->SetHeight(size.Height() * viewScale);
560     node->SetEnabledState(true);
561     node->SetClickableState(true);
562     node->SetFocusableState(true);
563     node->AddSupportAction(AceAction::ACTION_CLICK);
564     node->AddSupportAction(AceAction::ACTION_LONG_CLICK);
565 }
566 
HandleFinish(bool success)567 void RenderPickerBase::HandleFinish(bool success)
568 {
569     if (!data_) {
570         LOGE("data is null.");
571         return;
572     }
573 
574     if (data_->GetSubsidiary() && data_->GetAnimationController()) {
575         auto controller = data_->GetAnimationController();
576         controller->Play(false);
577         return;
578     }
579 
580     if (success) {
581         data_->OnSelectedSaving();
582     }
583 
584     if (success && onChangeCallback_) {
585         auto str = data_->GetSelectedObject(false, "");
586         onChangeCallback_(std::make_shared<DatePickerChangeEvent>(str));
587     }
588 
589     if (success && onJSChangeCallback_) {
590         onJSChangeCallback_(std::string("\"change\",") + data_->GetSelectedObject(false, "") + ",null");
591     }
592 
593     if (!success && onCancelCallback_) {
594         onCancelCallback_();
595     }
596 
597     if (onTextCancel_) {
598         onTextCancel_();
599     }
600 
601     if (data_->GetIsCreateDialogComponent()) {
602         if (success && onDialogAccept_) {
603             onDialogAccept_(std::string("\"change\",") + data_->GetSelectedObject(false, "") + ",null");
604         } else if (!success && onDialogCancel_) {
605             onDialogCancel_();
606         }
607     }
608     data_->HideDialog();
609 }
610 
HandleSwitch(bool checked)611 void RenderPickerBase::HandleSwitch(bool checked)
612 {
613     if (!data_) {
614         LOGE("data is null.");
615         return;
616     }
617 
618     std::vector<std::string> tags;
619     data_->OnLunarCallback(checked, tags);
620     for (const auto& tag : tags) {
621         auto iter = std::find_if(columns_.begin(), columns_.end(),
622             [&tag](const RefPtr<RenderPickerColumn>& column) { return column->GetColumnTag() == tag; });
623         if (iter != columns_.end()) {
624             (*iter)->FlushCurrentOptions();
625         }
626     }
627 }
628 
HandleColumnChange(const std::string & tag,bool isAdd,uint32_t index,bool needNotify)629 void RenderPickerBase::HandleColumnChange(const std::string& tag, bool isAdd, uint32_t index, bool needNotify)
630 {
631     if (!data_) {
632         LOGE("data is null.");
633         return;
634     }
635 
636     if (onColumnChangeCallback_ && needNotify) {
637         onColumnChangeCallback_(std::string("\"columnchange\",") + data_->GetSelectedObject(true, tag) + ",null");
638     }
639 
640     if (onTextAccept_) {
641         onTextAccept_(tag, index);
642     }
643 
644     std::vector<std::string> tags;
645     data_->OnDataLinking(tag, isAdd, index, tags);
646     for (const auto& tag : tags) {
647         auto iter = std::find_if(columns_.begin(), columns_.end(),
648             [&tag](const RefPtr<RenderPickerColumn>& column) { return column->GetColumnTag() == tag; });
649         if (iter != columns_.end()) {
650             (*iter)->FlushCurrentOptions();
651         }
652     }
653 
654     if (!data_->GetIsDialog() && !data_->GetIsCreateDialogComponent()) {
655         HandleFinish(true);
656         RefPtr<PickerColumnComponent> pickerColumn = data_->GetColumn(tag);
657         if (!pickerColumn) {
658             LOGE("pickerColumn Component is null");
659             return;
660         }
661         if (onTextChange_) {
662             onTextChange_(pickerColumn->GetCurrentText(), pickerColumn->GetCurrentIndex());
663         }
664         return;
665     }
666 
667     if (data_->GetIsCreateDialogComponent() && onDialogChange_) {
668         onDialogChange_(std::string("\"columnchange\",") + data_->GetSelectedObject(true, "") + ",null");
669     }
670 
671     data_->OnTitleBuilding();
672     auto titleComponent = data_->GetTitle();
673     if (data_->GetHasTitle()) {
674         if (title_ && titleComponent) {
675             title_->Update(titleComponent);
676         } else {
677             LOGE("render title or title component is null.");
678         }
679     }
680 }
681 
UpdateRenders()682 void RenderPickerBase::UpdateRenders()
683 {
684     ClearRenders();
685     GetRenders();
686     InitPickerAnimation();
687     switchHandlerSetted_ = false;
688 }
689 
GetRenders()690 void RenderPickerBase::GetRenders()
691 {
692     auto render = GetParent().Upgrade();
693     while (render && !AceType::InstanceOf<RenderStack>(render)) {
694         render = render->GetParent().Upgrade();
695     }
696     if (render) {
697         stack_ = AceType::DynamicCast<RenderStack>(render);
698     }
699     GetRenders(AceType::Claim(this));
700 }
701 
InitPickerAnimation()702 void RenderPickerBase::InitPickerAnimation()
703 {
704     if (!data_) {
705         LOGE("data is null for picker animation");
706         return;
707     }
708 
709     auto controller = data_->GetAnimationController();
710     if (!controller) {
711         LOGE("controller is null for picker animation.");
712         return;
713     }
714 
715     controller->SetPipeline(GetContext());
716     if (lunarDisplay_) {
717         controller->SetLunar(lunarDisplay_);
718     }
719     if (buttonsDisplay_) {
720         controller->SetButtons(buttonsDisplay_);
721     }
722     if (triangle_) {
723         controller->SetTriangle(triangle_);
724     }
725 
726     for (const auto& column : columns_) {
727         if (!column) {
728             continue;
729         }
730 
731         if (column->GetColumnTag() == PickerBaseComponent::PICKER_YEAR_COLUMN) {
732             controller->SetYear(column);
733         }
734         if (column->GetColumnTag() == PickerBaseComponent::PICKER_MONTH_COLUMN) {
735             controller->SetMonth(column);
736         }
737         if (column->GetColumnTag() == PickerBaseComponent::PICKER_DAY_COLUMN) {
738             controller->SetDay(column);
739         }
740         if (column->GetColumnTag() == PickerBaseComponent::PICKER_MONTHDAY_COLUMN) {
741             controller->SetMonthDay(column);
742         }
743         if (column->GetColumnTag() == PickerBaseComponent::PICKER_AMPM_COLUMN) {
744             controller->SetAmPm(column);
745         }
746         if (column->GetColumnTag() == PickerBaseComponent::PICKER_HOUR_COLUMN) {
747             controller->SetHour(column);
748         }
749         if (column->GetColumnTag() == PickerBaseComponent::PICKER_MINUTE_COLUMN) {
750             controller->SetMinute(column);
751         }
752         if (column->GetColumnTag() == PickerBaseComponent::PICKER_SECOND_COLUMN) {
753             controller->SetSecond(column);
754         }
755     }
756 }
757 
DealRenders(const RefPtr<RenderNode> & render)758 void RenderPickerBase::DealRenders(const RefPtr<RenderNode>& render)
759 {
760     if (AceType::InstanceOf<RenderDisplay>(render)) {
761         if (!buttonsDisplay_) {
762             buttonsDisplay_ = AceType::DynamicCast<RenderDisplay>(render);
763         } else {
764             auto temp = buttonsDisplay_;
765             buttonsDisplay_ = AceType::DynamicCast<RenderDisplay>(render);
766             lunarDisplay_ = temp;
767         }
768     }
769 
770     if (AceType::InstanceOf<RenderBox>(render)) {
771         auto parent = render->GetParent().Upgrade();
772         if (parent && AceType::InstanceOf<RenderPickerBase>(parent)) {
773             outBox_ = AceType::DynamicCast<RenderBox>(render);
774         }
775         if (parent && AceType::InstanceOf<RenderBox>(parent)) {
776             auto grand = parent->GetParent().Upgrade();
777             if (grand && AceType::InstanceOf<RenderPickerBase>(grand)) {
778                 box_ = AceType::DynamicCast<RenderBox>(render);
779             }
780         }
781     }
782 }
783 
GetRenders(const RefPtr<RenderNode> & render)784 void RenderPickerBase::GetRenders(const RefPtr<RenderNode>& render)
785 {
786     if (!render) {
787         return;
788     }
789 
790     if (AceType::InstanceOf<RenderTriangle>(render)) {
791         triangle_ = AceType::DynamicCast<RenderTriangle>(render);
792         return;
793     }
794 
795     if (AceType::InstanceOf<RenderCheckbox>(render)) {
796         switch_ = AceType::DynamicCast<RenderCheckbox>(render);
797         return;
798     }
799 
800     if (AceType::InstanceOf<RenderButton>(render)) {
801         auto gesture = AceType::DynamicCast<RenderButton>(render);
802         if (!cancel_ && !ok_) {
803             cancel_ = gesture;
804             return;
805         }
806         ok_ = gesture;
807         return;
808     }
809 
810     if (AceType::InstanceOf<RenderPickerColumn>(render)) {
811         auto column = AceType::DynamicCast<RenderPickerColumn>(render);
812         columns_.push_back(column);
813         if (!columnParent_ && column->GetParent().Upgrade()) {
814             columnParent_ = column->GetParent().Upgrade();
815         }
816         return;
817     }
818 
819     if (AceType::InstanceOf<RenderText>(render)) {
820         auto parent = render->GetParent().Upgrade();
821         if (parent && AceType::InstanceOf<RenderBox>(parent)) {
822             title_ = AceType::DynamicCast<RenderText>(render);
823             return;
824         }
825         if (parent && AceType::InstanceOf<RenderFlex>(parent)) {
826             lunarText_ = AceType::DynamicCast<RenderText>(render);
827             return;
828         }
829     }
830 
831     DealRenders(render);
832     for (const auto& child : render->GetChildren()) {
833 #if defined(PREVIEW)
834         child->SetAccessibilityNode(nullptr);
835 #endif
836         GetRenders(child);
837     }
838 }
839 
ClearRenders()840 void RenderPickerBase::ClearRenders()
841 {
842     title_ = nullptr;
843     triangle_ = nullptr;
844     lunarDisplay_ = nullptr;
845     buttonsDisplay_ = nullptr;
846     stack_ = nullptr;
847     box_ = nullptr;
848     outBox_ = nullptr;
849     cancel_ = nullptr;
850     ok_ = nullptr;
851     columns_.clear();
852     columnParent_ = nullptr;
853     switch_ = nullptr;
854     lunarText_ = nullptr;
855 }
856 
InitializeSelectedOption(const RefPtr<RenderPickerColumn> & pickerColumn)857 void RenderPickerBase::InitializeSelectedOption(const RefPtr<RenderPickerColumn>& pickerColumn)
858 {
859     for (const auto& option : pickerColumn->GetOptions()) {
860         if (!option->GetSelected()) {
861             continue;
862         }
863 
864         auto focusRenderBox = option->GetRenderBox();
865         if (!focusRenderBox) {
866             break;
867         }
868 
869         focusBoxSize_ = focusRenderBox->GetLayoutSize();
870         focusBoxOffset_ = focusRenderBox->GetGlobalOffset() - GetGlobalOffset();
871         break;
872     }
873 }
874 
GetBgColorBox() const875 const RefPtr<RenderBox> RenderPickerBase::GetBgColorBox() const
876 {
877     auto parent = GetParent().Upgrade();
878     while (parent && !parent->IsHeadRenderNode()) {
879         if (AceType::InstanceOf<RenderBox>(parent)) {
880             return AceType::DynamicCast<RenderBox>(parent);
881         }
882 
883         parent = parent->GetParent().Upgrade();
884     }
885 
886     if (AceType::InstanceOf<RenderBox>(parent)) {
887         return AceType::DynamicCast<RenderBox>(parent);
888     }
889 
890     return nullptr;
891 }
892 
893 } // namespace OHOS::Ace
894