• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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