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