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_time_picker.h" 17#include <cstdio> 18#include <ctime> 19#include "draw/draw_rect.h" 20#include "gfx_utils/graphic_log.h" 21#include "securec.h" 22#include "themes/theme_manager.h" 23 24namespace OHOS { 25UITimePicker::UITimePicker() 26 : selectedValue_{0}, 27 selectedHour_{0}, 28 selectedMinute_{0}, 29 selectedSecond_{0}, 30 secVisible_(false), 31 loopState_{false}, 32 pickerWidth_(0), 33 itemsHeight_(0), 34 xPos_(0), 35 backgroundFontSize_(0), 36 highlightFontSize_(0), 37 backgroundFontName_(nullptr), 38 highlightFontName_(nullptr), 39 pickerListener_(this), 40 timePickerListener_(nullptr) 41{ 42 Theme* theme = ThemeManager::GetInstance().GetCurrent(); 43 if (theme != nullptr) { 44 style_ = &(theme->GetPickerBackgroundStyle()); 45 } else { 46 style_ = &(StyleDefault::GetPickerBackgroundStyle()); 47 } 48 backgroundFontId_ = style_->font_; 49 backgroundColor_ = style_->textColor_; 50 if (theme != nullptr) { 51 style_ = &(theme->GetPickerHighlightStyle()); 52 } else { 53 style_ = &(StyleDefault::GetPickerHighlightStyle()); 54 } 55#if ENABLE_FOCUS_MANAGER 56 focusable_ = true; 57#endif 58 highlightFontId_ = style_->font_; 59 highlightColor_ = style_->textColor_; 60 61 hourPicker_ = nullptr; 62 minutePicker_ = nullptr; 63 secondPicker_ = nullptr; 64} 65 66UITimePicker::~UITimePicker() 67{ 68 DeInitTimePicker(); 69 if (backgroundFontName_ != nullptr) { 70 UIFree(backgroundFontName_); 71 backgroundFontName_ = nullptr; 72 } 73 74 if (highlightFontName_ != nullptr) { 75 UIFree(highlightFontName_); 76 highlightFontName_ = nullptr; 77 } 78} 79 80void UITimePicker::InitTimePicker() 81{ 82 xPos_ = 0; 83 if (secVisible_) { 84 pickerWidth_ = GetWidth() / SEC_VISIBLE_COUNT; 85 InitPicker(hourPicker_, TIME_START, HOUR_END); 86 xPos_ = pickerWidth_; 87 InitPicker(minutePicker_, TIME_START, MIN_END); 88 xPos_ *= (SEC_VISIBLE_COUNT - 1); 89 InitPicker(secondPicker_, TIME_START, SEC_END); 90 if (secondPicker_ != nullptr) { 91 secondPicker_->SetLoopState(loopState_[PICKER_SEC]); 92 } 93 } else { 94 pickerWidth_ = GetWidth() / SEC_INVISIBLE_COUNT; 95 InitPicker(hourPicker_, TIME_START, HOUR_END); 96 xPos_ = pickerWidth_; 97 InitPicker(minutePicker_, TIME_START, MIN_END); 98 } 99 if (hourPicker_ != nullptr) { 100 hourPicker_->SetLoopState(loopState_[PICKER_HOUR]); 101 } 102 if (minutePicker_ != nullptr) { 103 minutePicker_->SetLoopState(loopState_[PICKER_MIN]); 104 } 105 106 RefreshSelected(selectedValue_); 107} 108 109void UITimePicker::DeInitTimePicker() 110{ 111 DeInitPicker(secondPicker_); 112 DeInitPicker(minutePicker_); 113 DeInitPicker(hourPicker_); 114} 115 116void UITimePicker::RefreshTimePicker() 117{ 118 DeInitTimePicker(); 119 InitTimePicker(); 120} 121 122void UITimePicker::InitPicker(UIPicker*& picker, int16_t start, int16_t end) 123{ 124 picker = new UIPicker(); 125 if (picker == nullptr) { 126 GRAPHIC_LOGE("new UIPicker fail"); 127 return; 128 } 129 picker->SetPosition(xPos_, 0, pickerWidth_, GetHeight()); 130 picker->SetItemHeight(itemsHeight_); 131 picker->SetFontId(backgroundFontId_, highlightFontId_); 132 if ((backgroundFontName_ == nullptr) || (highlightFontName_ == nullptr)) { 133 picker->SetFontId(backgroundFontId_, highlightFontId_); 134 } else { 135 picker->SetBackgroundFont(backgroundFontName_, backgroundFontSize_); 136 picker->SetHighlightFont(highlightFontName_, highlightFontSize_); 137 } 138 picker->SetTextColor(backgroundColor_, highlightColor_); 139 picker->SetValues(start, end); 140 picker->RegisterSelectedListener(&pickerListener_); 141 Add(picker); 142 143#if ENABLE_ROTATE_INPUT 144 if (end == HOUR_END) { 145 picker->GetChildrenHead()->SetViewId(HOUR_LIST_NAME); 146 } else if (end == MIN_END && secondPicker_ == nullptr) { 147 picker->GetChildrenHead()->SetViewId(MIN_LIST_NAME); 148 } else if (end == SEC_END) { 149 picker->GetChildrenHead()->SetViewId(SEC_LIST_NAME); 150 } 151#endif 152} 153 154void UITimePicker::DeInitPicker(UIPicker*& picker) 155{ 156 if (picker != nullptr) { 157 Remove(picker); 158 picker->ClearValues(); 159 delete picker; 160 picker = nullptr; 161 } 162} 163 164void UITimePicker::TimeSelectedCallback() 165{ 166 uint16_t hourSelect = hourPicker_->GetSelected(); 167 uint16_t minSelect = minutePicker_->GetSelected(); 168 GetValueByIndex(selectedHour_, BUF_SIZE, hourSelect, TIME_START, HOUR_END); 169 GetValueByIndex(selectedMinute_, BUF_SIZE, minSelect, TIME_START, MIN_END); 170 171 if (memset_s(selectedValue_, SELECTED_VALUE_SIZE, 0, SELECTED_VALUE_SIZE) != EOK) { 172 return; 173 } 174 175 if (secVisible_) { 176 uint16_t secSelect = secondPicker_->GetSelected(); 177 GetValueByIndex(selectedSecond_, BUF_SIZE, secSelect, TIME_START, SEC_END); 178 if (sprintf_s(selectedValue_, SELECTED_VALUE_SIZE, "%s:%s:%s", 179 selectedHour_, selectedMinute_, selectedSecond_) < 0) { 180 return; 181 } 182 } else { 183 if (sprintf_s(selectedValue_, SELECTED_VALUE_SIZE, "%s:%s", selectedHour_, selectedMinute_) < 0) { 184 return; 185 } 186 } 187 188 if (timePickerListener_ != nullptr) { 189 timePickerListener_->OnTimePickerStoped(*this); 190 } 191} 192 193void UITimePicker::GetValueByIndex(char* value, uint8_t len, uint16_t index, int16_t start, int16_t end) 194{ 195 if ((value != nullptr) && (index < end - start + 1)) { 196 if (sprintf_s(value, len, "%02u", index) < 0) { 197 return; 198 } 199 } 200} 201 202bool UITimePicker::SetSelected(const char* value) 203{ 204 if (value == nullptr) { 205 return false; 206 } 207 208 if (memset_s(selectedValue_, SELECTED_VALUE_SIZE, 0, SELECTED_VALUE_SIZE) != EOK) { 209 return false; 210 } 211 212 if (strcpy_s(selectedValue_, SELECTED_VALUE_SIZE, value) != EOK) { 213 return false; 214 } 215 if (secVisible_) { 216 if (sscanf_s(value, "%[^:]%*c%[^:]%*c%[^\n]", selectedHour_, BUF_SIZE, 217 selectedMinute_, BUF_SIZE, selectedSecond_, BUF_SIZE) < 3) { // 3: three variables 218 return false; 219 } 220 } else { 221 if (sscanf_s(value, "%[^:]%*c%[^\n]", selectedHour_, BUF_SIZE, 222 selectedMinute_, BUF_SIZE) < 2) { // 2: two variables 223 return false; 224 } 225 } 226 return RefreshSelected(selectedValue_); 227} 228 229bool UITimePicker::RefreshSelected(const char* value) 230{ 231 uint32_t hourSelect; 232 uint32_t minSelect; 233 234 if (value == nullptr) { 235 return false; 236 } 237 238 if (secVisible_) { 239 uint32_t secSelect; 240 // 3: three variables 241 if (sscanf_s(value, "%u:%u:%u", &hourSelect, &minSelect, &secSelect) < 3) { 242 return false; 243 } 244 secondPicker_->SetSelected(secSelect); 245 } else { 246 if (sscanf_s(value, "%u:%u", &hourSelect, &minSelect) < 2) { // 2: two variables 247 return false; 248 } 249 } 250 251 hourPicker_->SetSelected(hourSelect); 252 minutePicker_->SetSelected(minSelect); 253 return true; 254} 255 256bool UITimePicker::OnPressEvent(const PressEvent& event) 257{ 258 if (event.GetCurrentPos().x < (GetX() + hourPicker_->GetX() + hourPicker_->GetWidth())) { 259 hourPicker_->RequestFocus(); 260 } else if (event.GetCurrentPos().x < (GetX() + minutePicker_->GetX() + minutePicker_->GetWidth())) { 261 minutePicker_->RequestFocus(); 262 } else if (event.GetCurrentPos().x < (GetX() + secondPicker_->GetX() + secondPicker_->GetWidth())) { 263 secondPicker_->RequestFocus(); 264 } 265 return UIView::OnPressEvent(event); 266} 267 268void UITimePicker::SetItemHeight(int16_t height) 269{ 270 itemsHeight_ = height; 271 RefreshTimePicker(); 272} 273 274void UITimePicker::EnableSecond(bool state) 275{ 276 secVisible_ = state; 277 RefreshTimePicker(); 278} 279 280void UITimePicker::SetTextStyle(uint16_t backgroundFontId, 281 uint16_t highlightFontId, 282 ColorType backgroundColor, 283 ColorType highlightColor) 284{ 285 highlightFontId_ = highlightFontId; 286 if (highlightFontName_ != nullptr) { 287 UIFree(highlightFontName_); 288 highlightFontName_ = nullptr; 289 } 290 291 backgroundFontId_ = backgroundFontId; 292 if (backgroundFontName_ != nullptr) { 293 UIFree(backgroundFontName_); 294 backgroundFontName_ = nullptr; 295 } 296 297 highlightColor_ = highlightColor; 298 backgroundColor_ = backgroundColor; 299 RefreshTimePicker(); 300} 301 302void UITimePicker::SetTextColor(ColorType backgroundColor, ColorType highlightColor) 303{ 304 backgroundColor_ = backgroundColor; 305 highlightColor_ = highlightColor; 306 RefreshTimePicker(); 307} 308 309void UITimePicker::SetBackgroundFont(const char* name, uint8_t size) 310{ 311 Text::SetFont(name, size, backgroundFontName_, backgroundFontSize_); 312 RefreshTimePicker(); 313} 314 315void UITimePicker::SetHighlightFont(const char* name, uint8_t size) 316{ 317 Text::SetFont(name, size, highlightFontName_, highlightFontSize_); 318 RefreshTimePicker(); 319} 320 321void UITimePicker::SetWidth(int16_t width) 322{ 323 UIView::SetWidth(width); 324 RefreshTimePicker(); 325} 326 327void UITimePicker::SetHeight(int16_t height) 328{ 329 UIView::SetHeight(height); 330 RefreshTimePicker(); 331} 332 333void UITimePicker::SetLoopState(const uint8_t pickerType, bool state) 334{ 335 switch (pickerType) { 336 case PICKER_HOUR: 337 loopState_[PICKER_HOUR] = state; 338 break; 339 case PICKER_MIN: 340 loopState_[PICKER_MIN] = state; 341 break; 342 case PICKER_SEC: 343 loopState_[PICKER_SEC] = state; 344 break; 345 default: 346 return; 347 } 348 RefreshTimePicker(); 349} 350} 351