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 textAdapter_->SetData(start, end);
217 RefreshList();
218 RefreshSelected(userSelectIndex);
219 return true;
220 }
221
RefreshValues(const char * value[],uint16_t count)222 bool UIPicker::RefreshValues(const char* value[], uint16_t count)
223 {
224 if (value == nullptr) {
225 return false;
226 }
227 maxCount_ = count;
228 if (!isWidthSet_ || !isHeightSet_ || !itemsHeight_) {
229 return false;
230 }
231 uint16_t userSelectIndex = listListener_->GetSelectIndex();
232 ClearList();
233 for (uint16_t i = 0; i < count; i++) {
234 dataList_.PushBack(value[i]);
235 }
236 InitTextAdapter();
237 textAdapter_->SetData(&dataList_);
238 RefreshList();
239 RefreshSelected(userSelectIndex);
240
241 return true;
242 }
243
RefreshList()244 void UIPicker::RefreshList()
245 {
246 int16_t height = GetHeight();
247 itemsWidth_ = GetWidth();
248 textAdapter_->SetWidth(itemsWidth_);
249 textAdapter_->SetHeight(itemsHeight_);
250 textAdapter_->SetLineBreakMode(UILabel::LINE_BREAK_CLIP);
251 if (backgroundFontName_ == nullptr) {
252 textAdapter_->SetFontId(backgroundFontId_);
253 } else {
254 textAdapter_->SetFont(backgroundFontName_, backgroundFontSize_);
255 }
256 textAdapter_->GetStyle().textColor_ = backgroundColor_;
257 textAdapter_->SetDirect(direct_);
258 list_.SetHeight(height);
259 list_.SetWidth(itemsWidth_);
260 list_.LayoutCenterOfParent();
261 list_.SetSelectPosition(height / 2); // 2: half
262 if (isScrollBlankSizeSet_) {
263 list_.SetScrollBlankSize(scrollBlankSize_);
264 } else {
265 list_.SetScrollBlankSize((height - itemsHeight_) / 2); // 2: half
266 }
267 if (!isSetAdaptered_) {
268 list_.SetAdapter(textAdapter_);
269 isSetAdaptered_ = true;
270 }
271
272 list_.RefreshList();
273 RefreshSelected(0);
274 }
275
ClearValues()276 void UIPicker::ClearValues()
277 {
278 rangeValue_ = nullptr;
279 rangeValueCount_ = 0;
280 maxCount_ = 0;
281 ClearList();
282 ClearTextAdapter();
283 }
284
ClearList()285 void UIPicker::ClearList()
286 {
287 itemsWidth_ = 0;
288 if (listListener_) {
289 listListener_->SetSelectView(nullptr);
290 listListener_->SetSelectIndex(0);
291 listListener_->SetInitStatus(false);
292 }
293 dataList_.Clear();
294 }
295
ClearTextAdapter()296 void UIPicker::ClearTextAdapter()
297 {
298 if (textAdapter_ != nullptr) {
299 delete textAdapter_;
300 textAdapter_ = nullptr;
301 }
302 list_.SetAdapter(textAdapter_);
303 list_.RefreshList();
304 isSetAdaptered_ = false;
305 }
306
SetSelected(uint16_t index)307 bool UIPicker::SetSelected(uint16_t index)
308 {
309 return RefreshSelected(index);
310 }
311
RefreshSelected(uint16_t index)312 bool UIPicker::RefreshSelected(uint16_t index)
313 {
314 if (maxCount_ <= index) {
315 GRAPHIC_LOGW("Failed to refresh selected since index is beyond range!");
316 return false;
317 }
318 if (itemsHeight_ && (list_.GetChildrenHead() != nullptr) && isWidthSet_ && isHeightSet_) {
319 listListener_->SetInitStatus(false);
320 // 2: half
321 int16_t yOffset = (list_.GetHeight() - itemsHeight_) / 2 -
322 itemsHeight_ * (index - list_.GetChildrenHead()->GetViewIndex());
323 list_.SetScrollStateListener(nullptr);
324 list_.ScrollBy(yOffset - list_.GetChildrenHead()->GetY());
325 list_.SetScrollStateListener(listListener_);
326 listListener_->SetScrollState(ListScrollListener::SCROLL_STATE_STOP);
327 UIView* childView = static_cast<UIView*>(list_.GetChildrenHead());
328 uint16_t lastSelectIndex = listListener_->GetSelectIndex();
329
330 while (childView != nullptr) {
331 int16_t viewIndex = childView->GetViewIndex();
332 if (viewIndex == lastSelectIndex) {
333 childView->SetStyle(STYLE_TEXT_COLOR, GetBackgroundTextColor().full);
334 if (backgroundFontName_ == nullptr) {
335 static_cast<UILabel*>(childView)->SetFontId(backgroundFontId_);
336 } else {
337 static_cast<UILabel*>(childView)->SetFont(backgroundFontName_, backgroundFontSize_);
338 }
339 }
340 if (viewIndex == index) {
341 childView->SetStyle(STYLE_TEXT_COLOR, GetHighlightTextColor().full);
342 if (highlightFontName_ == nullptr) {
343 static_cast<UILabel*>(childView)->SetFontId(highlightFontId_);
344 } else {
345 static_cast<UILabel*>(childView)->SetFont(highlightFontName_, highlightFontSize_);
346 }
347 listListener_->SetSelectView(childView);
348 listListener_->SetInitStatus(true);
349 }
350 childView = childView->GetNextSibling();
351 }
352 listListener_->SetSelectIndex(index);
353 list_.Invalidate();
354 return true;
355 }
356 listListener_->SetSelectIndex(index);
357 return false;
358 }
359
GetSelected() const360 uint16_t UIPicker::GetSelected() const
361 {
362 return listListener_->GetSelectIndex();
363 }
364
SetFontId(uint16_t backgroundFontId,uint16_t highlightFontId)365 void UIPicker::SetFontId(uint16_t backgroundFontId, uint16_t highlightFontId)
366 {
367 if ((backgroundFontId == backgroundFontId_) && (highlightFontId == highlightFontId_)) {
368 return;
369 }
370 backgroundFontId_ = backgroundFontId;
371 if (backgroundFontName_ != nullptr) {
372 UIFree(backgroundFontName_);
373 backgroundFontName_ = nullptr;
374 }
375
376 highlightFontId_ = highlightFontId;
377 if (highlightFontName_ != nullptr) {
378 UIFree(highlightFontName_);
379 highlightFontName_ = nullptr;
380 }
381
382 Refresh();
383 }
384
SetBackgroundFont(const char * name,uint8_t size)385 void UIPicker::SetBackgroundFont(const char* name, uint8_t size)
386 {
387 if ((name != nullptr) && (backgroundFontName_ != nullptr)) {
388 if (strcmp(name, backgroundFontName_) == 0 && size == backgroundFontSize_) {
389 return;
390 }
391 }
392 Text::SetFont(name, size, backgroundFontName_, backgroundFontSize_);
393 Refresh();
394 }
395
SetHighlightFont(const char * name,uint8_t size)396 void UIPicker::SetHighlightFont(const char* name, uint8_t size)
397 {
398 if ((name != nullptr) && (highlightFontName_ != nullptr)) {
399 if (strcmp(name, highlightFontName_) == 0 && size == highlightFontSize_) {
400 return;
401 }
402 }
403 Text::SetFont(name, size, highlightFontName_, highlightFontSize_);
404 Refresh();
405 }
406
SetTextColor(ColorType backgroundColor,ColorType highlightColor)407 void UIPicker::SetTextColor(ColorType backgroundColor, ColorType highlightColor)
408 {
409 if ((backgroundColor.full == backgroundColor_.full) && (highlightColor.full == highlightColor_.full)) {
410 return;
411 }
412 backgroundColor_ = backgroundColor;
413 highlightColor_ = highlightColor;
414 Refresh();
415 }
416
SetItemHeight(int16_t height)417 void UIPicker::SetItemHeight(int16_t height)
418 {
419 if (height == itemsHeight_) {
420 return;
421 }
422 if (height > 0) {
423 itemsHeight_ = height;
424 Refresh();
425 }
426 }
427
SetWidth(int16_t width)428 void UIPicker::SetWidth(int16_t width)
429 {
430 if (width == UIView::GetWidth()) {
431 return;
432 }
433 if (width > 0) {
434 UIView::SetWidth(width);
435 isWidthSet_ = true;
436 Refresh();
437 }
438 }
439
SetHeight(int16_t height)440 void UIPicker::SetHeight(int16_t height)
441 {
442 if (height == UIView::GetHeight()) {
443 return;
444 }
445 if (height > 0) {
446 UIView::SetHeight(height);
447 isHeightSet_ = true;
448 Refresh();
449 }
450 }
451
SetLoopState(bool state)452 void UIPicker::SetLoopState(bool state)
453 {
454 if (state == list_.GetLoopState()) {
455 return;
456 }
457 list_.SetLoopState(state);
458 Refresh();
459 }
460
SetDirect(UITextLanguageDirect direct)461 void UIPicker::SetDirect(UITextLanguageDirect direct)
462 {
463 if (direct == direct_) {
464 return;
465 }
466 direct_ = direct;
467 Refresh();
468 }
469
SetTextFormatter(TextFormatter * formatter)470 void UIPicker::SetTextFormatter(TextFormatter* formatter)
471 {
472 InitTextAdapter();
473 textAdapter_->SetTextFormatter(formatter);
474 Refresh();
475 }
476 } // namespace OHOS
477