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/button/button_element.h"
17 
18 #include "frameworks/core/common/container.h"
19 
20 namespace OHOS::Ace {
21 
CreateRenderNode()22 RefPtr<RenderNode> ButtonElement::CreateRenderNode()
23 {
24     RefPtr<RenderNode> node = ComponentGroupElement::CreateRenderNode();
25     if (node) {
26         auto wp = AceType::WeakClaim(this);
27         node->SetOnChangeCallback([wp]() {
28             auto button = wp.Upgrade();
29             if (button) {
30                 button->OnChange();
31             }
32         });
33     }
34     return node;
35 }
36 
Update()37 void ButtonElement::Update()
38 {
39     RenderElement::Update();
40 
41     button_ = AceType::DynamicCast<RenderButton>(renderNode_);
42     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(component_);
43     if (buttonComponent) {
44         SetFocusable(!buttonComponent->GetDisabledState() && buttonComponent->GetFocusable());
45     }
46 
47     auto labelTarget = AceType::DynamicCast<LabelTarget>(component_);
48     if (!labelTarget) {
49         // switch is not label target, button are label target
50         LOGW("not find label target");
51         return;
52     }
53     auto trigger = labelTarget->GetTrigger();
54     if (!trigger) {
55         // component not set label trigger
56         LOGW("get label trigger failed");
57         return;
58     }
59 
60     auto weak = AceType::WeakClaim(this);
61     trigger->clickHandler_ = [weak]() {
62         auto button = weak.Upgrade();
63         if (button) {
64             button->OnClick();
65         }
66     };
67 }
68 
LocalizedUpdate()69 void ButtonElement::LocalizedUpdate()
70 {
71     Update();
72     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(component_);
73 
74     if (Container::IsCurrentUsePartialUpdate() && buttonComponent->GetHasCustomChild()) {
75         // in partial update code path a custom child updates independently
76         return;
77     }
78     ComponentGroupElement::UpdateChildrenForDeclarative(buttonComponent->GetChildren());
79 }
80 
Apply(const RefPtr<Element> & child)81 void ButtonElement::Apply(const RefPtr<Element>& child)
82 {
83     RenderElement::Apply(child);
84     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(component_);
85     if (!buttonComponent) {
86         return;
87     }
88     if (buttonComponent->GetAutoFocusState()) {
89         auto wp = AceType::WeakClaim(this);
90         auto buttonElement = wp.Upgrade();
91         if (!buttonElement) {
92             return;
93         }
94 
95         buttonElement->RequestFocus();
96     }
97 }
98 
OnFocus()99 void ButtonElement::OnFocus()
100 {
101     if (!button_) {
102         return;
103     }
104     button_->HandleFocusEvent(true);
105     button_->PlayFocusAnimation(true);
106     auto context = context_.Upgrade();
107     if (context && context->GetIsTabKeyPressed()) {
108         button_->ChangeStatus(RenderStatus::FOCUS);
109     }
110 }
111 
OnClick()112 void ButtonElement::OnClick()
113 {
114     if (!button_) {
115         return;
116     }
117     button_->HandleClickEvent();
118     button_->HandleKeyEnterEvent();
119 }
120 
OnClick(const KeyEvent & event)121 bool ButtonElement::OnClick(const KeyEvent& event)
122 {
123     if (!button_) {
124         return false;
125     }
126     ClickInfo info(-1);
127     info.SetTimeStamp(event.timeStamp);
128     info.SetGlobalLocation(
129         Offset((GetRect().Left() + GetRect().Right()) / 2, (GetRect().Top() + GetRect().Bottom()) / 2));
130     info.SetLocalLocation(
131         Offset((GetRect().Right() - GetRect().Left()) / 2, (GetRect().Bottom() - GetRect().Top()) / 2));
132     info.SetSourceDevice(event.sourceType);
133     info.SetDeviceId(event.deviceId);
134     button_->HandleClickEvent(info);
135     return button_->HandleKeyEnterEvent(info);
136 }
137 
OnBlur()138 void ButtonElement::OnBlur()
139 {
140     if (!button_) {
141         return;
142     }
143     button_->HandleFocusEvent(false);
144     button_->PlayFocusAnimation(false);
145     auto context = context_.Upgrade();
146     if (!context) {
147         LOGE("Pipeline context is nullptr");
148         return;
149     }
150     if (context->GetIsTabKeyPressed()) {
151         button_->ChangeStatus(RenderStatus::BLUR);
152     }
153     context->CancelFocusAnimation();
154     context->CancelShadow();
155 }
156 
OnChange()157 void ButtonElement::OnChange()
158 {
159     if (button_ && IsCurrentFocus()) {
160         button_->DisplayFocusAnimation();
161     }
162 }
163 
164 } // namespace OHOS::Ace
165