• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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