[NUI] Add public types to replace nested types (CA1034 of StyleCop) (#1692)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / RecyclerView / RecyclerView.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 provides a View that can recycle items to improve performance.
25     /// </summary>
26     /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
27     [EditorBrowsable(EditorBrowsableState.Never)]
28     public class RecyclerView : ScrollableBase
29     {
30         protected RecycleAdapter mAdapter;
31         protected View mContainer;
32         protected RecycleLayoutManager mLayoutManager;
33         protected int mTotalItemCount = 15;
34         private List<PropertyNotification> notifications = new List<PropertyNotification>();
35
36         public RecyclerView() : base()
37         {
38             Initialize(new RecycleAdapter(), new RecycleLayoutManager());
39         }
40
41         /// <summary>
42         /// Default constructor.
43         /// </summary>
44         /// <param name="adapter">Recycle adapter of RecyclerView.</param>
45         /// <param name="layoutManager">Recycle layoutManager of RecyclerView.</param>
46         /// <since_tizen> 8 </since_tizen>
47         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
48         [EditorBrowsable(EditorBrowsableState.Never)]
49         public RecyclerView(RecycleAdapter adapter, RecycleLayoutManager layoutManager)
50         {
51             Initialize(adapter, layoutManager);
52         }
53
54         private void Initialize(RecycleAdapter adapter, RecycleLayoutManager layoutManager)
55         {
56             Scrolling += OnScrolling;
57
58             mAdapter = adapter;
59             mAdapter.OnDataChanged += OnAdapterDataChanged;
60
61             mLayoutManager = layoutManager;
62             mLayoutManager.Container = ContentContainer;
63             mLayoutManager.ItemSize = mAdapter.CreateRecycleItem().Size;
64             mLayoutManager.DataCount = mAdapter.Data.Count;
65
66             InitializeItems();
67         }
68
69         private void OnItemSizeChanged(object source, PropertyNotification.NotifyEventArgs args)
70         {
71             mLayoutManager.Layout(ScrollingDirection == Direction.Horizontal ? ContentContainer.CurrentPosition.X : ContentContainer.CurrentPosition.Y);
72         }
73         
74         public int TotalItemCount 
75         {
76             get
77             {
78                 return mTotalItemCount;
79             }
80             set
81             {
82                 mTotalItemCount = value;
83                 InitializeItems();
84             }
85         }
86
87         private void InitializeItems()
88         {
89             for(int i = Children.Count -1 ; i > -1 ; i--)
90             {
91                 Children[i].Unparent();
92                 notifications[i].Notified -= OnItemSizeChanged;
93                 notifications.RemoveAt(i);
94             }
95
96             for (int i = 0; i < mTotalItemCount; i++)
97             {
98                 RecycleItem item = mAdapter.CreateRecycleItem();
99                 item.DataIndex = i;
100                 item.Name = "[" + i + "] recycle";
101
102                 if (i < mAdapter.Data.Count)
103                 {
104                     mAdapter.BindData(item);
105                 }
106                 Add(item);
107
108                 PropertyNotification noti = item.AddPropertyNotification("size", PropertyCondition.Step(0.1f));
109                 noti.Notified += OnItemSizeChanged;
110                 notifications.Add(noti);
111             }
112
113             mLayoutManager.Layout(0.0f);
114
115             if (ScrollingDirection == Direction.Horizontal)
116             {
117                 ContentContainer.SizeWidth = mLayoutManager.CalculateLayoutOrientationSize();
118             }
119             else
120             {
121                 ContentContainer.SizeHeight = mLayoutManager.CalculateLayoutOrientationSize();
122             }
123         }
124
125
126         public new Direction ScrollingDirection
127         {
128             get
129             {
130                 return base.ScrollingDirection;
131             }
132             set
133             {
134                 base.ScrollingDirection = value;
135
136                 if (ScrollingDirection == Direction.Horizontal)
137                 {
138                     ContentContainer.SizeWidth = mLayoutManager.CalculateLayoutOrientationSize();
139                 }
140                 else
141                 {
142                     ContentContainer.SizeHeight = mLayoutManager.CalculateLayoutOrientationSize();
143                 }
144             }
145         }
146
147         /// <summary>
148         /// Recycler adpater.
149         /// </summary>
150         /// <since_tizen> 8 </since_tizen>
151         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
152         [EditorBrowsable(EditorBrowsableState.Never)]
153         public RecycleAdapter Adapter
154         {
155             get
156             {
157                 return mAdapter;
158             }
159             set
160             {
161                 if(mAdapter != null)
162                 {
163                     mAdapter.OnDataChanged -= OnAdapterDataChanged;
164                 }
165
166                 mAdapter = value;
167                 mAdapter.OnDataChanged += OnAdapterDataChanged;
168                 mLayoutManager.ItemSize = mAdapter.CreateRecycleItem().Size;
169                 mLayoutManager.DataCount = mAdapter.Data.Count;
170                 InitializeItems();
171             }
172         }
173
174         /// <summary>
175         /// Recycler layoutManager.
176         /// </summary>
177         /// <since_tizen> 8 </since_tizen>
178         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
179         [EditorBrowsable(EditorBrowsableState.Never)]
180         public RecycleLayoutManager LayoutManager
181         {
182             get
183             {
184                 return mLayoutManager;
185             }
186             set
187             {
188                 mLayoutManager = value;
189                 mLayoutManager.Container = ContentContainer;
190                 mLayoutManager.ItemSize = mAdapter.CreateRecycleItem().Size;
191                 mLayoutManager.DataCount = mAdapter.Data.Count;
192                 InitializeItems();
193             }
194         }
195
196         private void OnScrolling(object source, ScrollEventArgs args)
197         {
198             mLayoutManager.Layout(ScrollingDirection == Direction.Horizontal ? args.Position.X : args.Position.Y);
199             List<RecycleItem> recycledItemList = mLayoutManager.Recycle(ScrollingDirection == Direction.Horizontal ? args.Position.X : args.Position.Y);
200             BindData(recycledItemList);
201         }
202
203         private void OnAdapterDataChanged(object source, EventArgs args)
204         {
205             List<RecycleItem> changedData = new List<RecycleItem>();
206
207             foreach (RecycleItem item in Children)
208             {
209                 changedData.Add(item);
210             }
211
212             BindData(changedData);
213         }
214
215         private void BindData(List<RecycleItem> changedData)
216         {
217             foreach (RecycleItem item in changedData)
218             {
219                 if (item.DataIndex > -1 && item.DataIndex < mAdapter.Data.Count)
220                 {
221                     item.Show();
222                     item.Name = "["+item.DataIndex+"]";
223                     mAdapter.BindData(item);
224                 }
225                 else
226                 {
227                     item.Hide();
228                 }
229             }
230         }
231
232         /// <summary>
233         /// Adjust scrolling position by own scrolling rules.
234         /// Override this function when developer wants to change destination of flicking.(e.g. always snap to center of item)
235         /// </summary>
236         /// <param name="position">Scroll position which is calculated by ScrollableBase</param>
237         /// <returns>Adjusted scroll destination</returns>
238         /// <since_tizen> 8 </since_tizen>
239         /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
240         [EditorBrowsable(EditorBrowsableState.Never)]
241         protected override float AdjustTargetPositionOfScrollAnimation(float position)
242         {
243             // Destination is depending on implementation of layout manager.
244             // Get destination from layout manager.
245             return mLayoutManager.CalculateCandidateScrollPosition(position);
246         }
247     }
248 }