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 22namespace OHOS { 23PickerListScrollListener::PickerListScrollListener(UIPicker* picker, UIList* list) 24 : listView_(list), 25 pickerView_(picker), 26 selectView_(nullptr), 27 lastSelectView_(nullptr), 28 selectIndex_(0), 29 isInitted_(false) {} 30 31void 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 60void 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 93UIPicker::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 148UIPicker::~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 173bool 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 184bool 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 195void UIPicker::Refresh() 196{ 197 if (rangeValue_) { 198 RefreshValues(rangeValue_, rangeValueCount_); 199 } else if ((startValue_ != 0) || (endValue_ != 0)) { 200 RefreshValues(startValue_, endValue_); 201 } 202} 203 204bool 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 222bool 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 244void 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 276void UIPicker::ClearValues() 277{ 278 rangeValue_ = nullptr; 279 rangeValueCount_ = 0; 280 maxCount_ = 0; 281 ClearList(); 282 ClearTextAdapter(); 283} 284 285void 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 296void 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 307bool UIPicker::SetSelected(uint16_t index) 308{ 309 return RefreshSelected(index); 310} 311 312bool 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 360uint16_t UIPicker::GetSelected() const 361{ 362 return listListener_->GetSelectIndex(); 363} 364 365void 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 385void 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 396void 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 407void 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 417void 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 428void 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 440void 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 452void UIPicker::SetLoopState(bool state) 453{ 454 if (state == list_.GetLoopState()) { 455 return; 456 } 457 list_.SetLoopState(state); 458 Refresh(); 459} 460 461void UIPicker::SetDirect(UITextLanguageDirect direct) 462{ 463 if (direct == direct_) { 464 return; 465 } 466 direct_ = direct; 467 Refresh(); 468} 469 470void UIPicker::SetTextFormatter(TextFormatter* formatter) 471{ 472 InitTextAdapter(); 473 textAdapter_->SetTextFormatter(formatter); 474 Refresh(); 475} 476} // namespace OHOS 477