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