1 /* 2 * Copyright (c) 2021-2022 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_TAB_BAR_RENDER_TAB_CONTENT_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_TAB_BAR_RENDER_TAB_CONTENT_H 18 19 #include <functional> 20 #include <unordered_map> 21 22 #include "base/memory/ace_type.h" 23 #include "core/animation/animation.h" 24 #include "core/animation/animator.h" 25 #include "core/components/tab_bar/tab_content_component.h" 26 #include "core/gestures/drag_recognizer.h" 27 #include "core/gestures/raw_recognizer.h" 28 #include "core/pipeline/base/render_node.h" 29 30 namespace OHOS::Ace { 31 32 class RenderTabContent : public RenderNode { 33 DECLARE_ACE_TYPE(RenderTabContent, RenderNode) 34 35 public: 36 RenderTabContent(); 37 ~RenderTabContent() override = default; 38 39 static RefPtr<RenderNode> Create(); 40 void Update(const RefPtr<Component>& component) override; 41 void PerformLayout() override; 42 bool IsUseOnly() override; 43 44 using UpdateIndexFunc = std::function<void(int32_t index)>; RegisterCallback(const UpdateIndexFunc & callback)45 void RegisterCallback(const UpdateIndexFunc& callback) 46 { 47 callback_ = callback; 48 } 49 RegisterRequireCallback(const UpdateIndexFunc & callback)50 void RegisterRequireCallback(const UpdateIndexFunc& callback) 51 { 52 requireCallback_ = callback; 53 } 54 55 using UpdateIndicatorFunc = std::function<void(double percent, int32_t newIndex, bool needChange)>; RegisterIndicatorCallback(const UpdateIndicatorFunc & callback)56 void RegisterIndicatorCallback(const UpdateIndicatorFunc& callback) 57 { 58 indicatorCallback_ = callback; 59 } 60 61 void ChangeScroll(int32_t index, bool fromController = false); 62 63 void UpdateDragPosition(int32_t index); 64 AddChildContent(int32_t index,const RefPtr<RenderNode> & child)65 void AddChildContent(int32_t index, const RefPtr<RenderNode>& child) 66 { 67 LOGD("AddChildContent: %{public}d", index); 68 auto iter = contentMap_.begin(); 69 while (iter != contentMap_.end()) { 70 if (iter->second == child) { 71 if (iter->first != index) { 72 // index has changed, clear map. 73 contentMap_.clear(); 74 } 75 break; 76 } 77 iter++; 78 } 79 contentMap_[index] = child; 80 requestedIndex_ = index; 81 forceUpdate_ = true; 82 } 83 RemoveChildContent(int32_t index)84 void RemoveChildContent(int32_t index) 85 { 86 LOGD("RemoveChildContent: %{public}d", index); 87 if (contentMap_.find(index) != contentMap_.end()) { 88 contentMap_.clear(); 89 forceUpdate_ = true; 90 } 91 } 92 RemoveChildContent(const RefPtr<RenderNode> & child)93 void RemoveChildContent(const RefPtr<RenderNode>& child) 94 { 95 LOGD("RemoveChildContent by content"); 96 auto iter = contentMap_.begin(); 97 while (iter != contentMap_.end()) { 98 if (iter->second == child) { 99 iter->second->SetHidden(true); 100 contentMap_.clear(); 101 forceUpdate_ = true; 102 break; 103 } 104 iter++; 105 } 106 } 107 RemoveChildContentUpdateMap(const RefPtr<RenderNode> & child)108 void RemoveChildContentUpdateMap(const RefPtr<RenderNode>& child) 109 { 110 LOGD("RemoveChildContent by content, map update"); 111 int32_t idx = -1; 112 113 for (const auto& item : contentMap_) { 114 if (item.second == child) { 115 item.second->SetHidden(true); 116 idx = item.first; 117 break; 118 } 119 } 120 121 if (idx < 0) { 122 return; 123 } 124 125 std::unordered_map<int32_t, RefPtr<RenderNode>> newContentMap; 126 for (const auto& item : contentMap_) { 127 if (item.first < idx) { 128 newContentMap.emplace(item); 129 } else if (item.first > idx) { 130 newContentMap.emplace(std::pair<int32_t, RefPtr<RenderNode>>(item.first - 1, item.second)); 131 } 132 } 133 134 std::swap(contentMap_, newContentMap); 135 } 136 UpdateContentCount(int32_t count)137 void UpdateContentCount(int32_t count) 138 { 139 contentCount_ = count; 140 } 141 142 // Used by declarative element to flush index after performBuild. 143 void FlushIndex(); 144 GetCurrentIndex()145 int32_t GetCurrentIndex() const 146 { 147 return currentIndex_; 148 } 149 GetChildContents()150 const std::unordered_map<int32_t, RefPtr<RenderNode>>& GetChildContents() const 151 { 152 return contentMap_; 153 } 154 155 void FireDomChangeEvent(int32_t index) const; 156 IsScrollable()157 bool IsScrollable() const 158 { 159 return scrollable_; 160 } 161 GetScrollDuration()162 float GetScrollDuration() const 163 { 164 return scrollDuration_; 165 } 166 167 std::string ProvideRestoreInfo() override; 168 169 private: 170 // for handle scroll tabContent 171 void OnTouchTestHit( 172 const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) override; 173 void HandleDragStart(); 174 void HandleDragUpdate(double offset); 175 void HandleDragEnd(); 176 177 void Initialize(const WeakPtr<PipelineContext>& context); 178 void FireContentChangeEvent() const; 179 void HandContentIndicatorEvent(int32_t newIndex, bool needChange) const; 180 181 // used to scroll TabContent and update the position 182 void ScrollContents(int32_t newIndex, bool isLinkBar, bool fromController = false); 183 void UpdateScrollPosition(double dragDelta); 184 void UpdateChildPosition(double offset, int32_t currentIndex, int32_t newIndex, bool needChange); 185 void HandleStopListener(int32_t newIndex, bool needChange, bool FromController = false); 186 void HandleStartListener(int32_t newIndex, bool needChange, bool isLinkBar); 187 void SetHiddenChild(); 188 189 double GetOffset(double offset); 190 191 static double GetFriction(double percentage); 192 193 // if tab is vertical, offset changed on Y axis 194 // if tab is horizontal, offset changed on X axis GetMainAxisOffset(double offset)195 Offset GetMainAxisOffset(double offset) const 196 { 197 return isVertical_ ? Offset(0.0, offset) : Offset(offset, 0.0); 198 } 199 IsRightToLeft()200 bool IsRightToLeft() const 201 { 202 return GetTextDirection() == TextDirection::RTL && !isVertical_; 203 } 204 // used to get the previous index or the next index 205 int32_t GetPrevIndex() const; 206 int32_t GetNextIndex() const; 207 208 void ApplyRestoreInfo(); 209 210 // dragRecognizer and the animation 211 RefPtr<DragRecognizer> dragDetector_; 212 RefPtr<Animation<double>> translate_; 213 RefPtr<Animator> animator_; 214 215 // map for contents 216 std::unordered_map<int32_t, RefPtr<RenderNode>> contentMap_; 217 218 // onChange event 219 std::function<void(const std::string&)> changeEvent_; 220 std::function<void(uint32_t)> domChangeEvent_; 221 std::function<void(const std::shared_ptr<BaseEventInfo>&)> onChangeEvent_; 222 223 bool isAnimationAdded_ = false; // whether the animation is added 224 bool scrollable_ = true; // the default value is true 225 bool isInAnimation_ = false; // whether it is in animation 226 bool isDragging_ = false; // whether it is dragging 227 bool isInitialized_ = false; 228 bool isVertical_ = false; // whether the tab is vertical 229 bool forceUpdate_ = false; 230 231 int32_t contentCount_ = 0; // the count of content 232 int32_t currentIndex_ = 0; // the index of current tab 233 int32_t requestedIndex_ = -1; // the next requested index 234 235 float scrollDuration_ = 0.0f; // the duration of the scroll animation 236 double contentWidth_ = 0.0; // the width of tab content 237 double contentHeight_ = 0.0; // the height of tab content 238 double prevOffset_ = 0.0; // the offset of previous item 239 double nextOffset_ = 0.0; // the offset of next item 240 double scrollOffset_ = 0.0; // the offset when the content is scrolling 241 242 // callbacks when updating the index 243 UpdateIndexFunc callback_; 244 UpdateIndexFunc requireCallback_; 245 UpdateIndicatorFunc indicatorCallback_; 246 247 RefPtr<TabController> controller_; 248 bool useInitialIndex_ = true; 249 }; 250 251 } // namespace OHOS::Ace 252 253 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_TAB_BAR_RENDER_TAB_CONTENT_H 254