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