1 /*
2  * Copyright (c) 2021 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/stepper/stepper_element.h"
17 
18 #include "core/components/stepper/render_stepper.h"
19 
20 namespace OHOS::Ace {
21 namespace {
22 
23 constexpr int32_t ELEMENT_CHANGE_END_LISTENER_KEY = 1002;
24 constexpr int32_t RIGHT_BUTTON_INDEX = 1;
25 constexpr int32_t DEFAULT_BUTTON_NUM = 2;
26 
27 } // namespace
28 
PerformBuild()29 void StepperElement::PerformBuild()
30 {
31     if (!leftFocusNode_ && !rightFocusNode_) {
32         leftFocusNode_ = AceType::MakeRefPtr<FocusNode>();
33         FocusGroup::AddChild(leftFocusNode_);
34         rightFocusNode_ = AceType::MakeRefPtr<FocusNode>();
35         FocusGroup::AddChild(rightFocusNode_);
36         registerCallBack();
37     }
38     ComponentGroupElement::PerformBuild();
39 }
40 
registerCallBack()41 void StepperElement::registerCallBack()
42 {
43     leftFocusNode_->SetOnClickCallback([weak = WeakClaim(this)](void) {
44         auto client = weak.Upgrade();
45         if (client) {
46             client->HandleOnButtonClick(true);
47         }
48     });
49 
50     rightFocusNode_->SetOnClickCallback([weak = WeakClaim(this)](void) {
51         auto client = weak.Upgrade();
52         if (client) {
53             client->HandleOnButtonClick(false);
54         }
55     });
56 
57     leftFocusNode_->SetOnFocusCallback([weak = WeakClaim(this)](void) {
58         auto client = weak.Upgrade();
59         if (client) {
60             client->HandleOnButtonFocus(true, true);
61         }
62     });
63 
64     rightFocusNode_->SetOnFocusCallback([weak = WeakClaim(this)](void) {
65         auto client = weak.Upgrade();
66         if (client) {
67             client->HandleOnButtonFocus(true, false);
68         }
69     });
70 
71     leftFocusNode_->SetOnBlurCallback([weak = WeakClaim(this)](void) {
72         auto client = weak.Upgrade();
73         if (client) {
74             client->HandleOnButtonFocus(false, true);
75         }
76     });
77 
78     rightFocusNode_->SetOnBlurCallback([weak = WeakClaim(this)](void) {
79         auto client = weak.Upgrade();
80         if (client) {
81             client->HandleOnButtonFocus(false, false);
82         }
83     });
84 }
85 
CreateRenderNode()86 RefPtr<RenderNode> StepperElement::CreateRenderNode()
87 {
88     return ComponentGroupElement::CreateRenderNode();
89 }
90 
OnFocus()91 void StepperElement::OnFocus()
92 {
93     auto stepper = DynamicCast<RenderStepper>(renderNode_);
94     if (!stepper) {
95         LOGE("get render node failed");
96         itLastFocusNode_ = focusNodes_.end();
97         return;
98     }
99     stepper->OnStatusChanged(RenderStatus::FOCUS);
100 
101     auto currentFocusNode = focusNodes_.begin();
102     std::advance(currentFocusNode, RIGHT_BUTTON_INDEX);
103     if ((*currentFocusNode)->RequestFocusImmediately()) {
104         itLastFocusNode_ = currentFocusNode;
105         rightFocusNode_ = *itLastFocusNode_;
106     }
107     stepper->RegisterChangeEndListener(
108         ELEMENT_CHANGE_END_LISTENER_KEY, [this](int32_t index) { RequestChildFocus(index); });
109 }
110 
RequestChildFocus(int32_t index)111 void StepperElement::RequestChildFocus(int32_t index)
112 {
113     auto currentFocusNode = focusNodes_.begin();
114     std::advance(currentFocusNode, index + DEFAULT_BUTTON_NUM);
115     if (currentFocusNode != focusNodes_.end()) {
116         if ((*currentFocusNode)->RequestFocusImmediately()) {
117             itLastFocusNode_ = currentFocusNode;
118         }
119     }
120 }
121 
OnBlur()122 void StepperElement::OnBlur()
123 {
124     FocusGroup::OnBlur();
125     auto stepper = DynamicCast<RenderStepper>(renderNode_);
126     if (stepper) {
127         stepper->UnRegisterChangeEndListener(ELEMENT_CHANGE_END_LISTENER_KEY);
128         stepper->OnStatusChanged(RenderStatus::BLUR);
129     }
130 }
131 
HandleOnButtonClick(bool isLeft)132 void StepperElement::HandleOnButtonClick(bool isLeft)
133 {
134     auto stepper = DynamicCast<RenderStepper>(renderNode_);
135     if (!stepper) {
136         LOGE("get stepper render node failed");
137         return;
138     }
139     stepper->HandleButtonClick(isLeft);
140 }
141 
HandleOnButtonFocus(bool focus,bool isLeft)142 void StepperElement::HandleOnButtonFocus(bool focus, bool isLeft)
143 {
144     auto stepper = DynamicCast<RenderStepper>(renderNode_);
145     if (!stepper) {
146         LOGE("get stepper render node failed");
147         return;
148     }
149     stepper->UpdateButtonFocus(focus, isLeft);
150 }
151 
RequestNextFocus(bool vertical,bool reverse,const Rect & rect)152 bool StepperElement::RequestNextFocus(bool vertical, bool reverse, const Rect& rect)
153 {
154     if (*itLastFocusNode_ == leftFocusNode_) {
155         if (reverse) {
156             return RequestCurrentItemFocus();
157         } else {
158             return RequestRightButtonFocus();
159         }
160     } else if (*itLastFocusNode_ == rightFocusNode_) {
161         if (vertical && reverse) {
162             return RequestCurrentItemFocus();
163         }
164         if (!vertical && reverse) {
165             return RequestLeftButtonFocus();
166         }
167     } else {
168         if (vertical && !reverse) {
169             return RequestLeftButtonFocus();
170         }
171     }
172     return false;
173 }
174 
RequestLeftButtonFocus()175 bool StepperElement::RequestLeftButtonFocus()
176 {
177     auto currentFocusNode = focusNodes_.begin();
178     if ((*currentFocusNode)->RequestFocusImmediately()) {
179         itLastFocusNode_ = currentFocusNode;
180         leftFocusNode_ = *itLastFocusNode_;
181         return true;
182     }
183     return false;
184 }
185 
RequestRightButtonFocus()186 bool StepperElement::RequestRightButtonFocus()
187 {
188     auto currentFocusNode = focusNodes_.begin();
189     std::advance(currentFocusNode, 1);
190     if ((*currentFocusNode)->RequestFocusImmediately()) {
191         itLastFocusNode_ = currentFocusNode;
192         rightFocusNode_ = *itLastFocusNode_;
193         return true;
194     }
195     return false;
196 }
197 
RequestCurrentItemFocus()198 bool StepperElement::RequestCurrentItemFocus()
199 {
200     auto stepper = DynamicCast<RenderStepper>(renderNode_);
201     if (!stepper) {
202         LOGE("get stepper render node failed");
203         return false;
204     }
205     int32_t currentIndex = stepper->GetCurrentIndex();
206     auto currentFocusNode = focusNodes_.begin();
207     std::advance(currentFocusNode, currentIndex + DEFAULT_BUTTON_NUM);
208     if (currentFocusNode != focusNodes_.end()) {
209         if ((*currentFocusNode)->RequestFocusImmediately()) {
210             itLastFocusNode_ = currentFocusNode;
211             return true;
212         }
213     }
214     return false;
215 }
216 
OnKeyEvent(const KeyEvent & keyEvent)217 bool StepperElement::OnKeyEvent(const KeyEvent& keyEvent)
218 {
219     if (!IsCurrentFocus()) {
220         return false;
221     }
222 
223     if (itLastFocusNode_ != focusNodes_.end() && (*itLastFocusNode_)->HandleKeyEvent(keyEvent)) {
224         return true;
225     }
226 
227     if (FocusNode::OnKeyEvent(keyEvent)) {
228         return true;
229     }
230 
231     if (keyEvent.action != KeyAction::UP) {
232         return false;
233     }
234 
235     switch (keyEvent.code) {
236         case KeyCode::TV_CONTROL_UP:
237             return RequestNextFocus(true, true, GetRect());
238         case KeyCode::TV_CONTROL_DOWN:
239             return RequestNextFocus(true, false, GetRect());
240         case KeyCode::TV_CONTROL_LEFT:
241             return RequestNextFocus(false, true, GetRect());
242         case KeyCode::TV_CONTROL_RIGHT:
243             return RequestNextFocus(false, false, GetRect());
244         case KeyCode::KEY_TAB:
245             return RequestNextFocus(false, false, GetRect()) || RequestNextFocus(true, false, GetRect());
246         default:
247             return false;
248     }
249 }
250 
251 } // namespace OHOS::Ace
252