1 /* 2 * Copyright (c) 2022-2023 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TIME_PICKER_TIME_PICKER_ROW_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TIME_PICKER_TIME_PICKER_ROW_PATTERN_H 18 19 #include <optional> 20 21 #include "base/i18n/localization.h" 22 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" 23 #include "core/components_ng/pattern/time_picker/timepicker_column_pattern.h" 24 #include "core/components_ng/pattern/time_picker/timepicker_event_hub.h" 25 #include "core/components_ng/pattern/time_picker/timepicker_layout_property.h" 26 #include "core/components_ng/pattern/time_picker/timepicker_paint_method.h" 27 #include "core/components_ng/pattern/time_picker/timepicker_row_accessibility_property.h" 28 #include "core/components_v2/inspector/utils.h" 29 30 namespace OHOS::Ace::NG { 31 namespace { 32 const Dimension TIME_FOCUS_PAINT_WIDTH = 2.0_vp; 33 } 34 35 class TimePickerRowPattern : public LinearLayoutPattern { 36 DECLARE_ACE_TYPE(TimePickerRowPattern, LinearLayoutPattern); 37 38 public: TimePickerRowPattern()39 TimePickerRowPattern() : LinearLayoutPattern(false) {}; 40 41 ~TimePickerRowPattern() override = default; 42 IsAtomicNode()43 bool IsAtomicNode() const override 44 { 45 return true; 46 } 47 CreateEventHub()48 RefPtr<EventHub> CreateEventHub() override 49 { 50 return MakeRefPtr<TimePickerEventHub>(); 51 } 52 CreateNodePaintMethod()53 RefPtr<NodePaintMethod> CreateNodePaintMethod() override 54 { 55 auto paintMethod = MakeRefPtr<TimePickerPaintMethod>(); 56 paintMethod->SetEnabled(enabled_); 57 paintMethod->SetBackgroundColor(backgroundColor_); 58 return paintMethod; 59 } 60 CreateLayoutAlgorithm()61 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override 62 { 63 return MakeRefPtr<LinearLayoutAlgorithm>(); 64 } 65 SetConfirmNode(WeakPtr<FrameNode> buttonConfirmNode)66 void SetConfirmNode(WeakPtr<FrameNode> buttonConfirmNode) 67 { 68 weakButtonConfirm_ = buttonConfirmNode; 69 } 70 SetCancelNode(WeakPtr<FrameNode> buttonCancelNode)71 void SetCancelNode(WeakPtr<FrameNode> buttonCancelNode) 72 { 73 weakButtonCancel_ = buttonCancelNode; 74 } 75 76 void OnLanguageConfigurationUpdate() override; 77 CreateLayoutProperty()78 RefPtr<LayoutProperty> CreateLayoutProperty() override 79 { 80 return MakeRefPtr<TimePickerLayoutProperty>(); 81 } 82 CreateAccessibilityProperty()83 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 84 { 85 return MakeRefPtr<TimePickerRowAccessibilityProperty>(); 86 } 87 88 void OnColumnsBuilding(); 89 GetAllChildNode()90 const std::unordered_map<std::string, RefPtr<FrameNode>>& GetAllChildNode() 91 { 92 return allChildNode_; 93 } 94 95 void UpdateAllChildNode(); 96 97 void HandleHourColumnBuilding(); 98 99 void FlushColumn(); 100 101 void FlushAmPmFormatString(); 102 103 void OnDataLinking( 104 const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags); 105 106 void HandleHour12Change(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags); 107 108 void SetChangeCallback(ColumnChangeCallback&& value); 109 110 void HandleColumnChange(const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, bool needNotify); 111 112 void SetEventCallback(EventCallback&& value); 113 114 void FireChangeEvent(bool refresh); 115 116 std::string GetSelectedObject(bool isColumnChange, int32_t status = -1); 117 118 PickerTime GetCurrentTime(); 119 120 uint32_t GetHourFromAmPm(bool isAm, uint32_t amPmhour) const; 121 HasTitleNode()122 bool HasTitleNode() const 123 { 124 return titleId_.has_value(); 125 } 126 GetTitleId()127 int32_t GetTitleId() 128 { 129 if (!titleId_.has_value()) { 130 titleId_ = ElementRegister::GetInstance()->MakeUniqueId(); 131 } 132 return titleId_.value(); 133 } 134 GetShowCount()135 uint32_t GetShowCount() const 136 { 137 return showCount_; 138 } 139 SetShowCount(uint32_t showCount)140 void SetShowCount(uint32_t showCount) 141 { 142 showCount_ = showCount; 143 } 144 GetOptionCount(const RefPtr<FrameNode> & frameNode)145 uint32_t GetOptionCount(const RefPtr<FrameNode>& frameNode) 146 { 147 return optionsTotalCount_[frameNode]; 148 } 149 GetOptionValue(const RefPtr<FrameNode> & frmeNode,uint32_t index)150 std::string GetOptionValue(const RefPtr<FrameNode>& frmeNode, uint32_t index) 151 { 152 if (index >= GetOptionCount(frmeNode)) { 153 LOGE("index out of range."); 154 return nullptr; 155 } 156 return options_[frmeNode][index]; 157 } 158 HasDividerNode()159 bool HasDividerNode() const 160 { 161 return DividerId_.has_value(); 162 } 163 GetDividerId()164 int32_t GetDividerId() 165 { 166 if (!DividerId_.has_value()) { 167 DividerId_ = ElementRegister::GetInstance()->MakeUniqueId(); 168 } 169 return DividerId_.value(); 170 } 171 172 const std::string& GetOptionsValue(const RefPtr<FrameNode>& frameNode, uint32_t optionIndex); 173 GetOptionsCount()174 const std::map<RefPtr<FrameNode>, uint32_t>& GetOptionsCount() const 175 { 176 return optionsTotalCount_; 177 } 178 SetHour24(bool value)179 void SetHour24(bool value) 180 { 181 hour24_ = value; 182 } 183 GetHour24()184 bool GetHour24() const 185 { 186 auto timePickerLayoutProperty = GetLayoutProperty<TimePickerLayoutProperty>(); 187 CHECK_NULL_RETURN(timePickerLayoutProperty, hour24_); 188 return timePickerLayoutProperty->GetIsUseMilitaryTimeValue(hour24_); 189 } 190 ClearOptionsHour()191 void ClearOptionsHour() 192 { 193 // when switch IsUseMilitaryTime state, should clear options_[hourColumn] 194 // Hour24 : Index = [0, 23] -> hour = [0, 23] 195 // Hour12 : Index = [0, 11] -> hour = [1, 12] 196 auto hourColumn = allChildNode_["hour"]; 197 CHECK_NULL_VOID(hourColumn); 198 options_[hourColumn].clear(); 199 } 200 SetSelectedTime(const PickerTime & value)201 void SetSelectedTime(const PickerTime& value) 202 { 203 selectedTime_ = value; 204 } 205 GetSelectedTime()206 const PickerTime& GetSelectedTime() 207 { 208 return selectedTime_; 209 } 210 SetDialogTitleDate(const PickerDate & value)211 void SetDialogTitleDate(const PickerDate& value) 212 { 213 dialogTitleDate_ = value; 214 } 215 GetDialogTitleDate()216 const PickerDate& GetDialogTitleDate() 217 { 218 return dialogTitleDate_; 219 } 220 HasAmPmNode()221 bool HasAmPmNode() const 222 { 223 return amPmId_.has_value(); 224 } 225 GetAmPmId()226 int32_t GetAmPmId() 227 { 228 if (!amPmId_.has_value()) { 229 amPmId_ = ElementRegister::GetInstance()->MakeUniqueId(); 230 } 231 return amPmId_.value(); 232 } 233 HasHourNode()234 bool HasHourNode() const 235 { 236 return hourId_.has_value(); 237 } 238 GetHourId()239 int32_t GetHourId() 240 { 241 if (!hourId_.has_value()) { 242 hourId_ = ElementRegister::GetInstance()->MakeUniqueId(); 243 } 244 return hourId_.value(); 245 } 246 HasMinuteNode()247 bool HasMinuteNode() const 248 { 249 return minuteId_.has_value(); 250 } 251 GetMinuteId()252 int32_t GetMinuteId() 253 { 254 if (!minuteId_.has_value()) { 255 minuteId_ = ElementRegister::GetInstance()->MakeUniqueId(); 256 } 257 return minuteId_.value(); 258 } 259 GetHasSecond()260 bool GetHasSecond() const 261 { 262 return hasSecond_; 263 } SetHasSecond(bool value)264 void SetHasSecond(bool value) 265 { 266 hasSecond_ = value; 267 } 268 GetColumn(int32_t tag)269 RefPtr<FrameNode> GetColumn(int32_t tag) const 270 { 271 auto iter = std::find_if(timePickerColumns_.begin(), timePickerColumns_.end(), 272 [tag](const RefPtr<FrameNode>& column) { return column->GetId() == tag; }); 273 return (iter == timePickerColumns_.end()) ? nullptr : *iter; 274 } 275 SetColumn(const RefPtr<FrameNode> & value)276 void SetColumn(const RefPtr<FrameNode>& value) 277 { 278 timePickerColumns_.emplace_back(value); 279 } 280 SetBackgroundColor(const Color & color)281 void SetBackgroundColor(const Color& color) 282 { 283 backgroundColor_ = color; 284 } 285 286 bool IsAmHour(uint32_t hourOf24) const; 287 288 uint32_t GetAmPmHour(uint32_t hourOf24) const; 289 290 std::string GetAmFormatString() const; 291 292 std::string GetPmFormatString() const; 293 294 std::string AddZeroPrefix(const std::string& value) const; 295 296 std::string GetHourFormatString(uint32_t hour) const; 297 298 std::string GetMinuteFormatString(uint32_t minute) const; 299 GetFocusPattern()300 FocusPattern GetFocusPattern() const override 301 { 302 auto pipeline = PipelineBase::GetCurrentContext(); 303 CHECK_NULL_RETURN(pipeline, FocusPattern()); 304 auto pickerTheme = pipeline->GetTheme<PickerTheme>(); 305 CHECK_NULL_RETURN(pickerTheme, FocusPattern()); 306 auto focusColor = pickerTheme->GetFocusColor(); 307 FocusPaintParam focusPaintParams; 308 focusPaintParams.SetPaintColor(focusColor); 309 focusPaintParams.SetPaintWidth(TIME_FOCUS_PAINT_WIDTH); 310 return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParams }; 311 } 312 ToJsonValue(std::unique_ptr<JsonValue> & json)313 void ToJsonValue(std::unique_ptr<JsonValue>& json) const override 314 { 315 json->Put("selected", selectedTime_.ToString(false, false).c_str()); 316 } 317 318 void CreateAmPmNode(); 319 void OnColorConfigurationUpdate() override; 320 SetContentRowNode(RefPtr<FrameNode> & contentRowNode)321 void SetContentRowNode(RefPtr<FrameNode>& contentRowNode) 322 { 323 contentRowNode_ = contentRowNode; 324 } 325 SetbuttonTitleNode(RefPtr<FrameNode> & buttonTitleNode)326 void SetbuttonTitleNode(RefPtr<FrameNode>& buttonTitleNode) 327 { 328 buttonTitleNode_ = buttonTitleNode; 329 } 330 SetPickerTag(bool isPicker)331 void SetPickerTag(bool isPicker) 332 { 333 isPicker_ = isPicker; 334 } 335 336 void SetFocusDisable(); 337 void SetFocusEnable(); 338 339 private: 340 void OnModifyDone() override; 341 void OnAttachToFrameNode() override; 342 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 343 344 void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub); 345 bool OnKeyEvent(const KeyEvent& event); 346 bool HandleDirectionKey(KeyCode code); 347 void InitDisabled(); 348 void GetInnerFocusPaintRect(RoundRect& paintRect); 349 void PaintFocusState(); 350 void SetButtonIdeaSize(); 351 double SetAmPmButtonIdeaSize(); 352 353 RefPtr<ClickEvent> clickEventListener_; 354 bool enabled_ = true; 355 int32_t focusKeyID_ = 0; 356 std::unordered_map<std::string, RefPtr<FrameNode>> allChildNode_; 357 std::map<RefPtr<FrameNode>, std::unordered_map<uint32_t, std::string>> options_; 358 std::map<RefPtr<FrameNode>, uint32_t> optionsTotalCount_; 359 uint32_t showCount_ = 0; 360 Color backgroundColor_ = Color::WHITE; 361 // true, use 24 hours style; false, use 12 hours style. 362 bool hour24_ = !Localization::GetInstance()->IsAmPmHour(); 363 PickerTime selectedTime_ = PickerTime::Current(); 364 PickerDate dialogTitleDate_ = PickerDate::Current(); 365 std::optional<int32_t> amPmId_; 366 std::optional<int32_t> hourId_; 367 std::optional<int32_t> minuteId_; 368 std::optional<int32_t> titleId_; 369 std::optional<int32_t> ButtonTitleId_; 370 std::optional<int32_t> DividerId_; 371 WeakPtr<FrameNode> weakButtonConfirm_; 372 WeakPtr<FrameNode> weakButtonCancel_; 373 374 bool hasSecond_ = false; 375 std::vector<RefPtr<FrameNode>> timePickerColumns_; 376 std::vector<std::string> vecAmPm_ = Localization::GetInstance()->GetAmPmStrings(); 377 378 ACE_DISALLOW_COPY_AND_MOVE(TimePickerRowPattern); 379 380 RefPtr<FrameNode> buttonTitleNode_; 381 RefPtr<FrameNode> contentRowNode_; 382 bool isPicker_ = false; 383 }; 384 } // namespace OHOS::Ace::NG 385 386 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TIME_PICKER_TIME_PICKER_ROW_PATTERN_H 387