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_TEXT_PICKER_TEXT_PICKER_COLUMN_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TEXT_PICKER_TEXT_PICKER_COLUMN_PATTERN_H 18 19 #include <optional> 20 21 #include "core/components/common/properties/color.h" 22 #include "core/components/picker/picker_theme.h" 23 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" 24 #include "core/components_ng/pattern/picker/picker_type_define.h" 25 #include "core/components_ng/pattern/text/text_layout_property.h" 26 #include "core/components_ng/pattern/text_picker/textpicker_accessibility_property.h" 27 #include "core/components_ng/pattern/text_picker/textpicker_event_hub.h" 28 #include "core/components_ng/pattern/text_picker/textpicker_layout_algorithm.h" 29 #include "core/components_ng/pattern/text_picker/textpicker_layout_property.h" 30 #include "core/components_ng/pattern/text_picker/textpicker_overscroll.h" 31 #include "core/components_ng/pattern/text_picker/textpicker_paint_method.h" 32 #include "core/components_ng/pattern/text_picker/toss_animation_controller.h" 33 34 namespace OHOS::Ace::NG { 35 using EventCallback = std::function<void(bool)>; 36 using ColumnChangeCallback = std::function<void(const RefPtr<FrameNode>&, bool, uint32_t, bool)>; 37 38 struct TextProperties { 39 Dimension upFontSize; 40 Dimension fontSize; 41 Dimension downFontSize; 42 Color upColor; 43 Color currentColor; 44 Color downColor; 45 FontWeight upFontWeight; 46 FontWeight fontWeight; 47 FontWeight downFontWeight; 48 }; 49 50 struct TextPickerOptionProperty { 51 float height = 0.0f; 52 float fontheight = 0.0f; 53 float prevDistance = 0.0f; // between the prev item and itself when scroll up 54 float nextDistance = 0.0f; // between the next item and itself when scroll down 55 }; 56 57 class EventParam : public virtual AceType { 58 DECLARE_ACE_TYPE(EventParam, AceType) 59 60 public: 61 WeakPtr<FrameNode> instance; 62 int32_t itemIndex = 0; 63 int32_t itemTotalCounts = 0; 64 }; 65 66 enum class ScrollDirection { 67 UP = 0, 68 DOWN, 69 }; 70 71 enum class OptionIndex { 72 COLUMN_INDEX_0 = 0, 73 COLUMN_INDEX_1, 74 COLUMN_INDEX_2, 75 COLUMN_INDEX_3, 76 COLUMN_INDEX_4, 77 COLUMN_INDEX_5, 78 COLUMN_INDEX_6 79 }; 80 81 class TextPickerColumnPattern : public LinearLayoutPattern { 82 DECLARE_ACE_TYPE(TextPickerColumnPattern, LinearLayoutPattern); 83 84 public: TextPickerColumnPattern()85 TextPickerColumnPattern() : LinearLayoutPattern(true) {}; 86 87 ~TextPickerColumnPattern() override = default; 88 IsAtomicNode()89 bool IsAtomicNode() const override 90 { 91 return true; 92 } 93 CreateLayoutAlgorithm()94 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override 95 { 96 auto layoutAlgorithm = MakeRefPtr<TextPickerLayoutAlgorithm>(); 97 if (algorithmOffset_.size() == 0) { 98 ResetAlgorithmOffset(); 99 } 100 layoutAlgorithm->SetCurrentOffset(algorithmOffset_); 101 layoutAlgorithm->SetDefaultPickerItemHeight(defaultPickerItemHeight_); 102 return layoutAlgorithm; 103 } 104 CreateLayoutProperty()105 RefPtr<LayoutProperty> CreateLayoutProperty() override 106 { 107 return MakeRefPtr<LinearLayoutProperty>(true); 108 } 109 110 void FlushCurrentOptions(bool isDown = false, bool isUpateTextContentOnly = false, bool isDirectlyClear = false, 111 bool isUpdateAnimationProperties = false); 112 113 void InitilaScorllEvent(); 114 115 void UpdateCurrentOffset(float offset); 116 117 void UpdateColumnChildPosition(double offsetY); 118 GetOverscroller()119 TextPickerOverscroller& GetOverscroller() 120 { 121 return overscroller_; 122 } 123 124 bool CanMove(bool isDown) const; 125 126 bool NotLoopOptions() const; 127 128 bool InnerHandleScroll(bool isDown, bool isUpatePropertiesOnly = false, bool isUpdateAnimationProperties = false); 129 SetDefaultPickerItemHeight(double defaultPickerItemHeight)130 void SetDefaultPickerItemHeight(double defaultPickerItemHeight) 131 { 132 defaultPickerItemHeight_ = defaultPickerItemHeight; 133 } 134 135 uint32_t GetShowOptionCount() const; 136 137 std::string GetSelectedObject(bool isColumnChange, int32_t status = 0) const; 138 SetSelected(uint32_t value)139 void SetSelected(uint32_t value) 140 { 141 selectedIndex_ = value; 142 } GetSelected()143 uint32_t GetSelected() const 144 { 145 return selectedIndex_; 146 } 147 SetRange(const std::vector<std::string> & value)148 void SetRange(const std::vector<std::string>& value) 149 { 150 if (value.empty()) { 151 return; 152 } 153 range_ = value; 154 } 155 GetRange()156 const std::vector<std::string>& GetRange() const 157 { 158 return range_; 159 } 160 GetCurrentText()161 std::string GetCurrentText() const 162 { 163 return GetOption(GetCurrentIndex()); 164 } 165 GetCurrentIndex()166 uint32_t GetCurrentIndex() const 167 { 168 return currentIndex_; 169 } SetCurrentIndex(uint32_t value)170 void SetCurrentIndex(uint32_t value) 171 { 172 if (value != currentIndex_) { 173 isIndexChanged_ = true; 174 currentIndex_ = value; 175 } 176 } 177 GetOptionCount()178 uint32_t GetOptionCount() const 179 { 180 return options_.size(); 181 } 182 GetOption(uint32_t index)183 std::string GetOption(uint32_t index) const 184 { 185 if (index >= GetOptionCount()) { 186 return ""; 187 } 188 return options_[index].text_; 189 } 190 SetOptions(std::vector<NG::RangeContent> & value)191 void SetOptions(std::vector<NG::RangeContent>& value) 192 { 193 options_.clear(); 194 for (auto& content : value) { 195 options_.emplace_back(content); 196 } 197 } 198 ClearOptions()199 void ClearOptions() 200 { 201 options_.clear(); 202 } 203 SetColumnKind(int32_t kind)204 void SetColumnKind(int32_t kind) 205 { 206 columnkind_ = kind; 207 } 208 GetCurrentOffset()209 float GetCurrentOffset() const 210 { 211 return deltaSize_; 212 } 213 SetCurrentOffset(float deltaSize)214 void SetCurrentOffset(float deltaSize) 215 { 216 deltaSize_ = deltaSize; 217 } 218 GetToss()219 const RefPtr<TextPickerTossAnimationController>& GetToss() const 220 { 221 return tossAnimationController_; 222 } 223 HandleEventCallback(bool refresh)224 void HandleEventCallback(bool refresh) 225 { 226 if (EventCallback_) { 227 EventCallback_(refresh); 228 } 229 } 230 GetEventCallback()231 const EventCallback& GetEventCallback() const 232 { 233 return EventCallback_; 234 } 235 SetEventCallback(EventCallback && value)236 void SetEventCallback(EventCallback&& value) 237 { 238 EventCallback_ = value; 239 } 240 HandleScrollStopEventCallback(bool refresh)241 void HandleScrollStopEventCallback(bool refresh) 242 { 243 if (scrollStopEventCallback_) { 244 scrollStopEventCallback_(refresh); 245 } 246 } 247 GetScrollStopEventCallback()248 const EventCallback& GetScrollStopEventCallback() const 249 { 250 return scrollStopEventCallback_; 251 } 252 SetScrollStopEventCallback(EventCallback && value)253 void SetScrollStopEventCallback(EventCallback&& value) 254 { 255 scrollStopEventCallback_ = value; 256 } 257 SetLocalDownDistance(float value)258 void SetLocalDownDistance(float value) 259 { 260 localDownDistance_ = value; 261 } 262 GetLocalDownDistance()263 float GetLocalDownDistance() const 264 { 265 return localDownDistance_; 266 } 267 268 void UpdateToss(double offsetY); 269 270 void TossStoped(); 271 272 void UpdateScrollDelta(double delta); 273 CreateAccessibilityProperty()274 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 275 { 276 return MakeRefPtr<TextPickerAccessibilityProperty>(); 277 } 278 SetChangeCallback(ColumnChangeCallback && value)279 void SetChangeCallback(ColumnChangeCallback&& value) 280 { 281 changeCallback_ = value; 282 } 283 HandleChangeCallback(bool isAdd,bool needNotify)284 void HandleChangeCallback(bool isAdd, bool needNotify) 285 { 286 if (changeCallback_) { 287 changeCallback_(GetHost(), isAdd, GetCurrentIndex(), needNotify); 288 } 289 } 290 GetHalfDisplayCounts()291 int32_t GetHalfDisplayCounts() const 292 { 293 return halfDisplayCounts_; 294 } 295 GetOffset()296 double GetOffset() const 297 { 298 return offsetCurSet_; 299 } 300 SetYLast(double value)301 void SetYLast(double value) 302 { 303 yLast_ = value; 304 } 305 306 void TossAnimationStoped(); 307 308 void PlayResetAnimation(); 309 GetMidShiftDistance()310 std::vector<TextPickerOptionProperty> GetMidShiftDistance() const 311 { 312 return optionProperties_; 313 } 314 SetMainVelocity(double mainVelocity)315 void SetMainVelocity(double mainVelocity) 316 { 317 mainVelocity_ = mainVelocity; 318 } 319 GetMainVelocity()320 double GetMainVelocity() const 321 { 322 return mainVelocity_; 323 } 324 SetTossStatus(bool status)325 void SetTossStatus(bool status) 326 { 327 isTossStatus_ = status; 328 if (!status && NotLoopOptions() && !pressed_ && !isReboundInProgress_ && overscroller_.IsOverScroll()) { 329 // Start rebound animation when toss stoped 330 CreateReboundAnimation(overscroller_.GetOverScroll(), 0.0); 331 HandleScrollStopEventCallback(true); 332 } 333 } 334 GetTossStatus()335 bool GetTossStatus() const 336 { 337 return isTossStatus_; 338 } 339 SetYOffset(double value)340 void SetYOffset(double value) 341 { 342 yOffset_ = value; 343 } 344 GetTouchBreakStatus()345 bool GetTouchBreakStatus() const 346 { 347 return touchBreak_; 348 } 349 NeedResetOptionPropertyHeight(bool needOptionPropertyHeightReset)350 void NeedResetOptionPropertyHeight(bool needOptionPropertyHeightReset) 351 { 352 needOptionPropertyHeightReset_ = needOptionPropertyHeightReset; 353 } 354 isHover()355 bool isHover() const 356 { 357 return isHover_; 358 } 359 360 int32_t GetOverScrollDeltaIndex() const; 361 void SetCanLoop(bool isLoop); 362 SetScrollDirection(bool isDown)363 void SetScrollDirection(bool isDown) 364 { 365 isDownScroll_ = isDown; 366 } 367 IsDownScroll()368 bool IsDownScroll() 369 { 370 return isDownScroll_; 371 } 372 void ResetOptionPropertyHeight(); 373 void ResetTotalDelta(); 374 375 private: 376 void OnModifyDone() override; 377 void OnAttachToFrameNode() override; 378 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 379 380 bool OnKeyEvent(const KeyEvent& event); 381 bool HandleDirectionKey(KeyCode code); 382 383 void InitPanEvent(const RefPtr<GestureEventHub>& gestureHub); 384 void HandleDragStart(const GestureEvent& event); 385 void HandleDragMove(const GestureEvent& event); 386 void HandleDragEnd(); 387 void CreateAnimation(); 388 void CreateAnimation(double from, double to); 389 void CreateReboundAnimation(double from, double to); 390 void ScrollOption(double delta); 391 std::vector<TextPickerOptionProperty> optionProperties_; 392 std::vector<int32_t> algorithmOffset_; 393 void ResetAlgorithmOffset(); 394 void CalcAlgorithmOffset(double distancePercent); 395 void SetOptionShiftDistance(); 396 double GetShiftDistanceForLandscape(int32_t index, ScrollDirection dir); 397 double GetShiftDistance(int32_t index, ScrollDirection dir); 398 double GetSelectedDistance(int32_t index, int32_t nextIndex, ScrollDirection dir); 399 double GetUpCandidateDistance(int32_t index, int32_t nextIndex, ScrollDirection dir); 400 double GetDownCandidateDistance(int32_t index, int32_t nextIndex, ScrollDirection dir); 401 void OnTouchDown(); 402 void OnTouchUp(); 403 void ParseTouchListener(); 404 void ParseMouseEvent(); 405 void InitMouseAndPressEvent(); 406 void HandleMouseEvent(bool isHover); 407 void SetButtonBackgroundColor(const Color& pressColor); 408 void PlayPressAnimation(const Color& pressColor); 409 void FlushCurrentTextOptions(const RefPtr<TextPickerLayoutProperty>& textPickerLayoutProperty, 410 bool isUpateTextContentOnly, bool isDirectlyClear); 411 void FlushCurrentImageOptions(); 412 void FlushCurrentMixtureOptions( 413 const RefPtr<TextPickerLayoutProperty>& textPickerLayoutProperty, bool isUpateTextContentOnly); 414 void UpdatePickerTextProperties(const RefPtr<TextLayoutProperty>& textLayoutProperty, 415 const RefPtr<TextPickerLayoutProperty>& textPickerLayoutProperty, uint32_t currentIndex, uint32_t middleIndex, 416 uint32_t showCount); 417 void UpdateSelectedTextProperties(const RefPtr<PickerTheme>& pickerTheme, 418 const RefPtr<TextLayoutProperty>& textLayoutProperty, 419 const RefPtr<TextPickerLayoutProperty>& textPickerLayoutProperty); 420 void UpdateCandidateTextProperties(const RefPtr<PickerTheme>& pickerTheme, 421 const RefPtr<TextLayoutProperty>& textLayoutProperty, 422 const RefPtr<TextPickerLayoutProperty>& textPickerLayoutProperty); 423 void UpdateDisappearTextProperties(const RefPtr<PickerTheme>& pickerTheme, 424 const RefPtr<TextLayoutProperty>& textLayoutProperty, 425 const RefPtr<TextPickerLayoutProperty>& textPickerLayoutProperty); 426 void AddAnimationTextProperties(uint32_t currentIndex, const RefPtr<TextLayoutProperty>& textLayoutProperty); 427 void UpdateTextPropertiesLinear(bool isDown, double scale); 428 void TextPropertiesLinearAnimation(const RefPtr<TextLayoutProperty>& textLayoutProperty, uint32_t index, 429 uint32_t showCount, bool isDown, double scale); 430 void FlushAnimationTextProperties(bool isDown); 431 Dimension LinearFontSize(const Dimension& startFontSize, const Dimension& endFontSize, double percent); 432 void ClearCurrentTextOptions(const RefPtr<TextPickerLayoutProperty>& textPickerLayoutProperty, 433 bool isUpateTextContentOnly, bool isDirectlyClear); 434 435 RefPtr<TextPickerLayoutProperty> GetParentLayout() const; 436 RefPtr<TouchEventImpl> CreateItemTouchEventListener(); 437 void OnAroundButtonClick(RefPtr<EventParam> param); 438 void OnMiddleButtonTouchDown(); 439 void OnMiddleButtonTouchMove(); 440 void OnMiddleButtonTouchUp(); 441 int32_t GetMiddleButtonIndex(); 442 443 bool touchEventInit_ = false; 444 RefPtr<InputEvent> CreateMouseHoverEventListener(RefPtr<EventParam> param); 445 RefPtr<ClickEvent> CreateItemClickEventListener(RefPtr<EventParam> param); 446 void SetAccessibilityAction(); 447 448 void InitTextFontFamily(); 449 bool SpringCurveTailMoveProcess(bool useRebound, double& dragDelta); 450 void SpringCurveTailEndProcess(bool useRebound, bool stopMove); 451 void UpdateTextAccessibilityProperty(RefPtr<FrameNode>& textNode, int32_t virtualIndex, 452 std::list<RefPtr<UINode>>::iterator& iter, bool virtualIndexValidate); 453 454 float localDownDistance_ = 0.0f; 455 Color pressColor_; 456 Color hoverColor_; 457 EventCallback EventCallback_; 458 EventCallback scrollStopEventCallback_; 459 RefPtr<ClickEvent> clickEventListener_; 460 bool enabled_ = true; 461 int32_t focusKeyID_ = 0; 462 RefPtr<TouchEventImpl> touchListener_; 463 bool isPress_ = false; 464 bool isHover_ = false; 465 RefPtr<InputEvent> mouseEvent_; 466 double defaultPickerItemHeight_ = 0.0; 467 uint32_t selectedIndex_ = 0; 468 std::string selectedValue_; 469 std::vector<std::string> range_ { "" }; 470 uint32_t currentIndex_ = 0; 471 std::vector<NG::RangeContent> options_; 472 int32_t columnkind_ = 0; 473 int32_t currentChildIndex_ = 0; 474 float deltaSize_ = 0.0f; 475 double totalDragDelta_ = 0.0; 476 double yLast_ = 0.0; 477 double yOffset_ = 0.0; 478 double jumpInterval_ = 0.0; 479 Size optionSize_; 480 Dimension fixHeight_; 481 bool isIndexChanged_ = false; 482 483 RefPtr<PanEvent> panEvent_; 484 bool pressed_ = false; 485 double scrollDelta_ = 0.0; 486 bool animationCreated_ = false; 487 RefPtr<TextPickerTossAnimationController> tossAnimationController_ = 488 AceType::MakeRefPtr<TextPickerTossAnimationController>(); 489 RefPtr<NodeAnimatablePropertyFloat> scrollProperty_; 490 RefPtr<NodeAnimatablePropertyFloat> aroundClickProperty_; 491 std::shared_ptr<AnimationUtils::Animation> animation_; 492 std::shared_ptr<AnimationUtils::Animation> reboundAnimation_; 493 std::vector<TextProperties> animationProperties_; 494 float dividerSpacing_ = 0.0f; 495 float gradientHeight_ = 0.0f; 496 bool isReboundInProgress_ = false; 497 TextPickerOverscroller overscroller_; 498 ColumnChangeCallback changeCallback_; 499 500 int32_t halfDisplayCounts_ = 0; 501 502 double mainVelocity_ = 0.0; 503 float offsetCurSet_ = 0.0f; 504 float distancePercent_ = 0.0f; 505 bool isTossStatus_ = false; 506 bool clickBreak_ = false; 507 bool touchBreak_ = false; 508 bool animationBreak_ = false; 509 bool needOptionPropertyHeightReset_ = false; 510 bool isLoop_ = true; 511 bool isDownScroll_ = false; 512 513 bool hasAppCustomFont_ = false; 514 bool hasUserDefinedDisappearFontFamily_ = false; 515 bool hasUserDefinedNormalFontFamily_ = false; 516 bool hasUserDefinedSelectedFontFamily_ = false; 517 518 ACE_DISALLOW_COPY_AND_MOVE(TextPickerColumnPattern); 519 }; 520 } // namespace OHOS::Ace::NG 521 522 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TEXT_PICKER_TEXT_PICKER_COLUMN_PATTERN_H 523