[Bluetooth][Non-ACR] Fix Native callback GC issue (#1678)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / RecyclerView / LinearRecycleLayoutManager.cs
1 /* Copyright (c) 2020 Samsung Electronics Co., Ltd.
2  *
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 using System;
17 using Tizen.NUI.BaseComponents;
18 using System.Collections.Generic;
19 using System.ComponentModel;
20
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// [Draft] This class implements a linear box layout.
25     /// </summary>
26     /// <since_tizen> 8 </since_tizen>
27     /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
28     [EditorBrowsable(EditorBrowsableState.Never)]
29     public class LinearRecycleLayoutManager : RecycleLayoutManager
30     {
31         private int firstVisibleItemIndex = -1;
32         private int lastVisibleItemIndex = -1;
33
34         private bool IsItemVisible(float scrollPosition, RecycleItem item)
35         {
36             bool result = false;
37             View list = Container.GetParent() as View;
38
39             Vector2 visibleArea = new Vector2( Math.Abs(scrollPosition), 
40                 Math.Abs(scrollPosition) + (LayoutOrientation == Orientation.Horizontal?
41                                                 list.Size.Width:list.Size.Height)
42             );
43
44             float firstCheckPoint = LayoutOrientation == Orientation.Horizontal? item.Position.X:item.Position.Y;
45             float secondCheckPoint = LayoutOrientation == Orientation.Horizontal? 
46                                         firstCheckPoint + item.Size.Width:
47                                         firstCheckPoint + item.Size.Height;
48
49             // Tizen.Log.Error("NUI", "[1p] "+visibleArea.X+ " =< "+firstCheckPoint+" =< "+visibleArea.Y+" ==== \n");
50             // Tizen.Log.Error("NUI", "[2p] "+visibleArea.X+ " =< "+secondCheckPoint+" =< "+visibleArea.Y+" ==== \n");
51
52             result = (firstCheckPoint >= visibleArea.X && firstCheckPoint <= visibleArea.Y) || (secondCheckPoint >= visibleArea.X && secondCheckPoint <= visibleArea.Y);
53
54             return result;
55         }
56
57         /// <summary>
58         /// This is called to find out where items are lain out according to current scroll position.
59         /// </summary>
60         /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
61         /// <since_tizen> 8 </since_tizen>
62         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
63         public override void Layout(float scrollPosition)
64         {
65             firstVisibleItemIndex = -1;
66             lastVisibleItemIndex = -1;
67
68             RecycleItem previousItem = null;
69
70             for(int i = 0 ; i < Container.Children.Count ; i++)
71             {
72                 RecycleItem item = Container.Children[i] as RecycleItem;
73
74                 if(previousItem != null)
75                 {
76                     item.Position = LayoutOrientation == Orientation.Horizontal?
77                         new Position(
78                             previousItem.Position.X + (previousItem.CurrentSize.Width != 0 ?
79                                                             previousItem.CurrentSize.Width:
80                                                             previousItem.Size.Width),
81                             item.PositionY
82                         ):
83                         new Position(
84                             item.PositionX,
85                             previousItem.Position.Y + (previousItem.CurrentSize.Height != 0 ? 
86                                                             previousItem.CurrentSize.Height:
87                                                             previousItem.Size.Height)
88                         );
89                 }
90
91                 bool isVisible = IsItemVisible(scrollPosition, item);
92
93                 if(isVisible)
94                 {
95                     firstVisibleItemIndex = firstVisibleItemIndex == -1? i : firstVisibleItemIndex;
96                     lastVisibleItemIndex = i;
97                 }
98
99                 previousItem = item;
100
101                 // Tizen.Log.Error("NUI","["+item.DataIndex+"] "+item.Position.Y+" ==== \n");
102             }
103
104             if(mStepSize == 0)
105             {
106                 mStepSize = LayoutOrientation == Orientation.Horizontal?ItemSize.Width:ItemSize.Height;
107             }
108         }
109
110         /// <summary>
111         /// This is called to find out how much container size can be.
112         /// </summary>
113         /// <since_tizen> 8 </since_tizen>
114         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
115         [EditorBrowsable(EditorBrowsableState.Never)]
116         public override float CalculateLayoutOrientationSize()
117         {
118             return mStepSize * DataCount;
119         }
120
121         /// <summary>
122         /// This is called to find out which items should be recycled according to current scroll position.
123         /// </summary>
124         /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
125         /// <returns>List of RecycleItems which should be recycled.</returns>
126         /// <since_tizen> 8 </since_tizen>
127         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
128         public override List<RecycleItem> Recycle(float scrollPosition)
129         {
130             List<RecycleItem> result = new List<RecycleItem>();
131           
132             bool checkFront = (mPrevScrollPosition - scrollPosition) > 0;
133
134             if(checkFront)
135             {
136                 if(firstVisibleItemIndex > 3)
137                 {
138                     // Too many item is in front!!! move first item to back!!!!
139                     RecycleItem target = Container.Children[0] as RecycleItem;
140                     target.DataIndex = target.DataIndex + Container.Children.Count;
141                     target.SiblingOrder = Container.Children.Count - 1;
142
143                     result.Add(target);
144                 }
145             }
146             else
147             {
148                 if(lastVisibleItemIndex < Container.Children.Count - 3)
149                 {
150                     RecycleItem prevFirstItem = Container.Children[0] as RecycleItem;
151
152                     RecycleItem target = Container.Children[Container.Children.Count - 1] as RecycleItem;
153                     target.Position = new Position(
154                         LayoutOrientation == Orientation.Horizontal ? (prevFirstItem.Position.X - target.Size.Width) : prevFirstItem.Position.X,
155                         LayoutOrientation == Orientation.Horizontal ? prevFirstItem.Position.Y : (prevFirstItem.Position.Y - target.Size.Height)
156                     );
157                     target.DataIndex = target.DataIndex - Container.Children.Count;
158                     target.SiblingOrder = 0;
159
160                     result.Add(target);
161                 }
162             }
163
164             mPrevScrollPosition = scrollPosition;
165
166             return result;
167         }
168
169         /// <summary>
170         /// Adjust scrolling position by own scrolling rules.
171         /// </summary>
172         /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
173         /// <since_tizen> 8 </since_tizen>
174         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
175         public override float CalculateCandidateScrollPosition(float scrollPosition)
176         {
177             return scrollPosition;
178         }
179     }
180 }