1 /*
2 * Copyright (c) 2020-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 "components/ui_picker.h"
17 #include "dock/vibrator_manager.h"
18 #include "draw/draw_line.h"
19 #include "draw/draw_rect.h"
20 #include "themes/theme_manager.h"
21
22 namespace OHOS {
PickerListScrollListener(UIPicker * picker,UIList * list)23 PickerListScrollListener::PickerListScrollListener(UIPicker* picker, UIList* list)
24 : listView_(list),
25 pickerView_(picker),
26 selectView_(nullptr),
27 lastSelectView_(nullptr),
28 selectIndex_(0),
29 isInitted_(false) {}
30
OnItemSelected(int16_t index,UIView * view)31 void PickerListScrollListener::OnItemSelected(int16_t index, UIView* view)
32 {
33 if (!isInitted_) {
34 return;
35 }
36
37 if ((lastSelectView_ != nullptr) && (listView_ != nullptr) && (pickerView_ != nullptr) && (view != nullptr)) {
38 lastSelectView_->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetBackgroundTextColor().full);
39 if (pickerView_->backgroundFontName_ == nullptr) {
40 static_cast<UILabel*>(lastSelectView_)->SetFontId(pickerView_->backgroundFontId_);
41 } else {
42 static_cast<UILabel*>(lastSelectView_)
43 ->SetFont(pickerView_->backgroundFontName_, pickerView_->backgroundFontSize_);
44 }
45 view->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetHighlightTextColor().full);
46 if (pickerView_->highlightFontName_ == nullptr) {
47 static_cast<UILabel*>(view)->SetFontId(pickerView_->highlightFontId_);
48 } else {
49 static_cast<UILabel*>(view)->SetFont(pickerView_->highlightFontName_, pickerView_->highlightFontSize_);
50 }
51 lastSelectView_ = view;
52 selectIndex_ = index;
53 listView_->Invalidate();
54 if (pickerView_->pickerListener_) {
55 pickerView_->pickerListener_->OnPickerChanged(*pickerView_);
56 }
57 }
58 }
59
OnScrollEnd(int16_t index,UIView * view)60 void PickerListScrollListener::OnScrollEnd(int16_t index, UIView* view)
61 {
62 if ((view == nullptr) || (listView_ == nullptr) || (pickerView_ == nullptr)) {
63 return;
64 }
65
66 if (lastSelectView_ != nullptr) {
67 lastSelectView_->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetBackgroundTextColor().full);
68 if (pickerView_->backgroundFontName_ == nullptr) {
69 static_cast<UILabel*>(lastSelectView_)->SetFontId(pickerView_->backgroundFontId_);
70 } else {
71 static_cast<UILabel*>(lastSelectView_)
72 ->SetFont(pickerView_->backgroundFontName_, pickerView_->backgroundFontSize_);
73 }
74 lastSelectView_ = view;
75 }
76
77 view->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetHighlightTextColor().full);
78 if (pickerView_->highlightFontName_ == nullptr) {
79 static_cast<UILabel*>(view)->SetFontId(pickerView_->highlightFontId_);
80 } else {
81 static_cast<UILabel*>(view)->SetFont(pickerView_->highlightFontName_, pickerView_->highlightFontSize_);
82 }
83
84 listView_->Invalidate();
85 selectView_ = view;
86 selectIndex_ = index;
87
88 if (pickerView_->pickerListener_) {
89 pickerView_->pickerListener_->OnPickerStoped(*pickerView_);
90 }
91 }
92
UIPicker()93 UIPicker::UIPicker()
94 : isWidthSet_(false),
95 isHeightSet_(false),
96 textAdapter_(nullptr),
97 maxCount_(0),
98 isScrollBlankSizeSet_(false),
99 scrollBlankSize_(0),
100 backgroundFontSize_(0),
101 highlightFontSize_(0),
102 backgroundFontName_(nullptr),
103 highlightFontName_(nullptr),
104 itemsWidth_(0),
105 itemsHeight_(0),
106 rangeValue_(nullptr),
107 rangeValueCount_(0),
108 startValue_(0),
109 endValue_(0),
110 isSetAdaptered_(false),
111 pickerListener_(nullptr)
112 {
113 Theme* theme = ThemeManager::GetInstance().GetCurrent();
114 if (theme != nullptr) {
115 style_ = &(theme->GetPickerBackgroundStyle());
116 } else {
117 style_ = &(StyleDefault::GetPickerBackgroundStyle());
118 }
119 backgroundFontId_ = style_->font_;
120 backgroundColor_ = style_->textColor_;
121 direct_ = UITextLanguageDirect::TEXT_DIRECT_LTR;
122
123 if (theme != nullptr) {
124 style_ = &(theme->GetPickerHighlightStyle());
125 } else {
126 style_ = &(StyleDefault::GetPickerHighlightStyle());
127 }
128 highlightFontId_ = style_->font_;
129 highlightColor_ = style_->textColor_;
130
131 list_.SetThrowDrag(true);
132 list_.SetStyle(StyleDefault::GetBackgroundTransparentStyle());
133 #if ENABLE_ROTATE_INPUT
134 list_.rotateFactor_ = DEFAULT_PICKER_ROTATE_FACTOR;
135 list_.rotateThrowthreshold_ = PICKERVIEW_ROTATE_THROW_THRESHOLD;
136 list_.rotateAccCoefficient_ = PICKERVIEW_ROTATE_DISTANCE_COEFF;
137 #endif
138 #if ENABLE_FOCUS_MANAGER
139 focusable_ = true;
140 #endif
141 list_.SetLoopState(false);
142 list_.EnableAutoAlign(true);
143 listListener_ = new PickerListScrollListener(this, &list_);
144 list_.SetScrollStateListener(listListener_);
145 Add(&list_);
146 }
147
~UIPicker()148 UIPicker::~UIPicker()
149 {
150 ClearValues();
151 Remove(&list_);
152 if (listListener_ != nullptr) {
153 delete listListener_;
154 listListener_ = nullptr;
155 }
156
157 if (backgroundFontName_ != nullptr) {
158 UIFree(backgroundFontName_);
159 backgroundFontName_ = nullptr;
160 }
161
162 if (highlightFontName_ != nullptr) {
163 UIFree(highlightFontName_);
164 highlightFontName_ = nullptr;
165 }
166
167 if (textAdapter_ != nullptr) {
168 delete textAdapter_;
169 textAdapter_ = nullptr;
170 }
171 }
172
SetValues(int16_t start,int16_t end)173 bool UIPicker::SetValues(int16_t start, int16_t end)
174 {
175 if (start > end) {
176 return false;
177 }
178
179 startValue_ = start;
180 endValue_ = end;
181 return RefreshValues(start, end);
182 }
183
SetValues(const char * value[],uint16_t count)184 bool UIPicker::SetValues(const char* value[], uint16_t count)
185 {
186 if (value == nullptr) {
187 return false;
188 }
189
190 rangeValue_ = value;
191 rangeValueCount_ = count;
192 return RefreshValues(value, count);
193 }
194
Refresh()195 void UIPicker::Refresh()
196 {
197 if (rangeValue_) {
198 RefreshValues(rangeValue_, rangeValueCount_);
199 } else if ((startValue_ != 0) || (endValue_ != 0)) {
200 RefreshValues(startValue_, endValue_);
201 }
202 }
203
RefreshValues(int16_t start,int16_t end)204 bool UIPicker::RefreshValues(int16_t start, int16_t end)
205 {
206 if ((start == 0) && (end == 0)) {
207 return false;
208 }
209 maxCount_ = end - start + 1;
210 if (!isWidthSet_ || !isHeightSet_ || !itemsHeight_) {
211 return false;
212 }
213 uint16_t userSelectIndex = listListener_->GetSelectIndex();
214 ClearList();
215 InitTextAdapter();
216 if (textAdapter_ == nullptr) {
217 return false;
218 }
219 textAdapter_->SetData(start, end);
220 RefreshList();
221 RefreshSelected(userSelectIndex);
222 return true;
223 }
224
RefreshValues(const char * value[],uint16_t count)225 bool UIPicker::RefreshValues(const char* value[], uint16_t count)
226 {
227 if (value == nullptr) {
228 return false;
229 }
230 maxCount_ = count;
231 if (!isWidthSet_ || !isHeightSet_ || !itemsHeight_) {
232 return false;
233 }
234 uint16_t userSelectIndex = listListener_->GetSelectIndex();
235 ClearList();
236 for (uint16_t i = 0; i < count; i++) {
237 dataList_.PushBack(value[i]);
238 }
239 InitTextAdapter();
240 textAdapter_->SetData(&dataList_);
241 RefreshList();
242 RefreshSelected(userSelectIndex);
243
244 return true;
245 }
246
RefreshList()247 void UIPicker::RefreshList()
248 {
249 int16_t height = GetHeight();
250 itemsWidth_ = GetWidth();
251 textAdapter_->SetWidth(itemsWidth_);
252 textAdapter_->SetHeight(itemsHeight_);
253 textAdapter_->SetLineBreakMode(UILabel::LINE_BREAK_CLIP);
254 if (backgroundFontName_ == nullptr) {
255 textAdapter_->SetFontId(backgroundFontId_);
256 } else {
257 textAdapter_->SetFont(backgroundFontName_, backgroundFontSize_);
258 }
259 textAdapter_->GetStyle().textColor_ = backgroundColor_;
260 textAdapter_->SetDirect(direct_);
261 list_.SetHeight(height);
262 list_.SetWidth(itemsWidth_);
263 list_.LayoutCenterOfParent();
264 list_.SetSelectPosition(height / 2); // 2: half
265 if (isScrollBlankSizeSet_) {
266 list_.SetScrollBlankSize(scrollBlankSize_);
267 } else {
268 list_.SetScrollBlankSize((height - itemsHeight_) / 2); // 2: half
269 }
270 if (!isSetAdaptered_) {
271 list_.SetAdapter(textAdapter_);
272 isSetAdaptered_ = true;
273 }
274
275 list_.RefreshList();
276 RefreshSelected(0);
277 }
278
ClearValues()279 void UIPicker::ClearValues()
280 {
281 rangeValue_ = nullptr;
282 rangeValueCount_ = 0;
283 maxCount_ = 0;
284 ClearList();
285 ClearTextAdapter();
286 }
287
ClearList()288 void UIPicker::ClearList()
289 {
290 itemsWidth_ = 0;
291 if (listListener_) {
292 listListener_->SetSelectView(nullptr);
293 listListener_->SetSelectIndex(0);
294 listListener_->SetInitStatus(false);
295 }
296 dataList_.Clear();
297 }
298
ClearTextAdapter()299 void UIPicker::ClearTextAdapter()
300 {
301 if (textAdapter_ != nullptr) {
302 delete textAdapter_;
303 textAdapter_ = nullptr;
304 }
305 list_.SetAdapter(textAdapter_);
306 list_.RefreshList();
307 isSetAdaptered_ = false;
308 }
309
SetSelected(uint16_t index)310 bool UIPicker::SetSelected(uint16_t index)
311 {
312 return RefreshSelected(index);
313 }
314
RefreshSelected(uint16_t index)315 bool UIPicker::RefreshSelected(uint16_t index)
316 {
317 if (maxCount_ <= index) {
318 GRAPHIC_LOGW("Failed to refresh selected since index is beyond range!");
319 return false;
320 }
321 if (itemsHeight_ && (list_.GetChildrenHead() != nullptr) && isWidthSet_ && isHeightSet_) {
322 listListener_->SetInitStatus(false);
323 // 2: half
324 int16_t yOffset = (list_.GetHeight() - itemsHeight_) / 2 -
325 itemsHeight_ * (index - list_.GetChildrenHead()->GetViewIndex());
326 list_.SetScrollStateListener(nullptr);
327 list_.ScrollBy(yOffset - list_.GetChildrenHead()->GetY());
328 list_.SetScrollStateListener(listListener_);
329 listListener_->SetScrollState(ListScrollListener::SCROLL_STATE_STOP);
330 UIView* childView = static_cast<UIView*>(list_.GetChildrenHead());
331 uint16_t lastSelectIndex = listListener_->GetSelectIndex();
332
333 while (childView != nullptr) {
334 int16_t viewIndex = childView->GetViewIndex();
335 if (viewIndex == lastSelectIndex) {
336 childView->SetStyle(STYLE_TEXT_COLOR, GetBackgroundTextColor().full);
337 if (backgroundFontName_ == nullptr) {
338 static_cast<UILabel*>(childView)->SetFontId(backgroundFontId_);
339 } else {
340 static_cast<UILabel*>(childView)->SetFont(backgroundFontName_, backgroundFontSize_);
341 }
342 }
343 if (viewIndex == index) {
344 childView->SetStyle(STYLE_TEXT_COLOR, GetHighlightTextColor().full);
345 if (highlightFontName_ == nullptr) {
346 static_cast<UILabel*>(childView)->SetFontId(highlightFontId_);
347 } else {
348 static_cast<UILabel*>(childView)->SetFont(highlightFontName_, highlightFontSize_);
349 }
350 listListener_->SetSelectView(childView);
351 listListener_->SetInitStatus(true);
352 }
353 childView = childView->GetNextSibling();
354 }
355 listListener_->SetSelectIndex(index);
356 list_.Invalidate();
357 return true;
358 }
359 listListener_->SetSelectIndex(index);
360 return false;
361 }
362
GetSelected() const363 uint16_t UIPicker::GetSelected() const
364 {
365 return listListener_->GetSelectIndex();
366 }
367
SetFontId(uint16_t backgroundFontId,uint16_t highlightFontId)368 void UIPicker::SetFontId(uint16_t backgroundFontId, uint16_t highlightFontId)
369 {
370 if ((backgroundFontId == backgroundFontId_) && (highlightFontId == highlightFontId_)) {
371 return;
372 }
373 backgroundFontId_ = backgroundFontId;
374 if (backgroundFontName_ != nullptr) {
375 UIFree(backgroundFontName_);
376 backgroundFontName_ = nullptr;
377 }
378
379 highlightFontId_ = highlightFontId;
380 if (highlightFontName_ != nullptr) {
381 UIFree(highlightFontName_);
382 highlightFontName_ = nullptr;
383 }
384
385 Refresh();
386 }
387
SetBackgroundFont(const char * name,uint8_t size)388 void UIPicker::SetBackgroundFont(const char* name, uint8_t size)
389 {
390 if ((name != nullptr) && (backgroundFontName_ != nullptr)) {
391 if (strcmp(name, backgroundFontName_) == 0 && size == backgroundFontSize_) {
392 return;
393 }
394 }
395 Text::SetFont(name, size, backgroundFontName_, backgroundFontSize_);
396 Refresh();
397 }
398
SetHighlightFont(const char * name,uint8_t size)399 void UIPicker::SetHighlightFont(const char* name, uint8_t size)
400 {
401 if ((name != nullptr) && (highlightFontName_ != nullptr)) {
402 if (strcmp(name, highlightFontName_) == 0 && size == highlightFontSize_) {
403 return;
404 }
405 }
406 Text::SetFont(name, size, highlightFontName_, highlightFontSize_);
407 Refresh();
408 }
409
SetTextColor(ColorType backgroundColor,ColorType highlightColor)410 void UIPicker::SetTextColor(ColorType backgroundColor, ColorType highlightColor)
411 {
412 if ((backgroundColor.full == backgroundColor_.full) && (highlightColor.full == highlightColor_.full)) {
413 return;
414 }
415 backgroundColor_ = backgroundColor;
416 highlightColor_ = highlightColor;
417 Refresh();
418 }
419
SetItemHeight(int16_t height)420 void UIPicker::SetItemHeight(int16_t height)
421 {
422 if (height == itemsHeight_) {
423 return;
424 }
425 if (height > 0) {
426 itemsHeight_ = height;
427 Refresh();
428 }
429 }
430
SetWidth(int16_t width)431 void UIPicker::SetWidth(int16_t width)
432 {
433 if (width == UIView::GetWidth()) {
434 return;
435 }
436 if (width > 0) {
437 UIView::SetWidth(width);
438 isWidthSet_ = true;
439 Refresh();
440 }
441 }
442
SetHeight(int16_t height)443 void UIPicker::SetHeight(int16_t height)
444 {
445 if (height == UIView::GetHeight()) {
446 return;
447 }
448 if (height > 0) {
449 UIView::SetHeight(height);
450 isHeightSet_ = true;
451 Refresh();
452 }
453 }
454
SetLoopState(bool state)455 void UIPicker::SetLoopState(bool state)
456 {
457 if (state == list_.GetLoopState()) {
458 return;
459 }
460 list_.SetLoopState(state);
461 Refresh();
462 }
463
SetDirect(UITextLanguageDirect direct)464 void UIPicker::SetDirect(UITextLanguageDirect direct)
465 {
466 if (direct == direct_) {
467 return;
468 }
469 direct_ = direct;
470 Refresh();
471 }
472
SetTextFormatter(TextFormatter * formatter)473 void UIPicker::SetTextFormatter(TextFormatter* formatter)
474 {
475 InitTextAdapter();
476 textAdapter_->SetTextFormatter(formatter);
477 Refresh();
478 }
479 } // namespace OHOS
480