1 /* Copyright (c) 2020 Samsung Electronics 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
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 using Tizen.NUI.BaseComponents;
18 using System.Collections.Generic;
19 using System.ComponentModel;
21 namespace Tizen.NUI.Components
24 /// [Draft] This class implements a grid box layout.
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 GridRecycleLayoutManager : RecycleLayoutManager
34 /// [draft ]Get/Set the number of rows in the grid
36 /// <since_tizen> 8 </since_tizen>
37 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
38 [EditorBrowsable(EditorBrowsableState.Never)]
49 if (Container != null)
51 Layout(PrevScrollPosition);
56 private int columns = 1;
60 /// [Draft] Get/Set the number of columns in the grid
62 /// <since_tizen> 8 </since_tizen>
63 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
64 [EditorBrowsable(EditorBrowsableState.Never)]
75 if (Container != null)
77 Layout(PrevScrollPosition);
82 private int firstVisibleItemIndex = -1;
83 private int lastVisibleItemIndex = -1;
85 private bool IsItemVisible(float scrollPosition, RecycleItem item)
88 View list = Container.GetParent() as View;
93 Vector2 visibleArea = new Vector2(Math.Abs(scrollPosition),
94 Math.Abs(scrollPosition) + (LayoutOrientation == Orientation.Vertical ?
95 list.Size.Width : list.Size.Height)
98 float firstCheckPoint = LayoutOrientation == Orientation.Vertical ? item.Position.X : item.Position.Y;
99 float secondCheckPoint = LayoutOrientation == Orientation.Vertical ?
100 firstCheckPoint + item.Size.Width :
101 firstCheckPoint + item.Size.Height;
103 result = (firstCheckPoint >= visibleArea.X && firstCheckPoint <= visibleArea.Y) || (secondCheckPoint >= visibleArea.X && secondCheckPoint <= visibleArea.Y);
109 /// This is called to find out how much container size can be.
111 /// <since_tizen> 8 </since_tizen>
112 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
113 [EditorBrowsable(EditorBrowsableState.Never)]
114 public override float CalculateLayoutOrientationSize()
116 float orientationFactor = LayoutOrientation == Orientation.Vertical ? Rows : Columns;
117 return StepSize * (int)Math.Ceiling((double)DataCount / (double)orientationFactor);
122 /// This is called to find out where items are lain out according to current scroll position.
124 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
125 /// <since_tizen> 8 </since_tizen>
126 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
127 public override void Layout(float scrollPosition)
129 int itemInGroup = LayoutOrientation == Orientation.Vertical ? Rows : Columns;
130 firstVisibleItemIndex = -1;
131 lastVisibleItemIndex = -1;
133 RecycleItem previousItem = null;
135 for (int i = 0; i < Container.Children.Count; i++)
137 RecycleItem item = Container.Children[i] as RecycleItem;
139 if (previousItem != null && item != null)
141 item.Position = LayoutOrientation == Orientation.Vertical ?
143 (i % itemInGroup == 0 ?
144 previousItem.Position.X + (previousItem.CurrentSize.Width != 0 ?
145 previousItem.CurrentSize.Width :
146 previousItem.Size.Width) :
147 previousItem.Position.X),
148 (i % itemInGroup == 0 ?
150 previousItem.PositionY + (previousItem.CurrentSize.Height != 0 ?
151 previousItem.CurrentSize.Height :
152 previousItem.Size.Height))
155 (i % itemInGroup == 0 ?
157 previousItem.PositionX + (previousItem.CurrentSize.Width != 0 ?
158 previousItem.CurrentSize.Width :
159 previousItem.Size.Width)),
160 (i % itemInGroup == 0 ?
161 previousItem.Position.Y + (previousItem.CurrentSize.Height != 0 ?
162 previousItem.CurrentSize.Height :
163 previousItem.Size.Height) :
164 previousItem.Position.Y)
168 bool isVisible = IsItemVisible(scrollPosition, item);
172 firstVisibleItemIndex = firstVisibleItemIndex == -1 ? i : firstVisibleItemIndex;
173 lastVisibleItemIndex = i;
181 StepSize = LayoutOrientation == Orientation.Vertical ? ItemSize.Width : ItemSize.Height;
187 /// This is called to find out which items should be recycled according to current scroll position.
189 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
190 /// <returns>List of RecycleItems which should be recycled.</returns>
191 /// <since_tizen> 8 </since_tizen>
192 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
193 public override List<RecycleItem> Recycle(float scrollPosition)
195 List<RecycleItem> result = new List<RecycleItem>();
196 bool checkFront = (PrevScrollPosition - scrollPosition) > 0;
198 int itemInGroup = LayoutOrientation == Orientation.Vertical ? Rows : Columns;
202 int currentGroupNum = (int)(firstVisibleItemIndex / itemInGroup) + 1;
204 if (currentGroupNum > 2)
206 // Too many item is in front!!! move first item to back!!!!
207 for (int i = 0; i < itemInGroup; i++)
209 RecycleItem target = Container.Children[0] as RecycleItem;
212 target.DataIndex = target.DataIndex + Container.Children.Count;
213 target.SiblingOrder = Container.Children.Count - 1;
222 int currentGroupNum = (int)(lastVisibleItemIndex / itemInGroup) + 1;
224 if (currentGroupNum < (int)(Container.Children.Count / itemInGroup) - 3)
226 for (int i = 0; i < itemInGroup; i++)
228 RecycleItem prevFirstItem = Container.Children[itemInGroup] as RecycleItem;
229 RecycleItem target = Container.Children[Container.Children.Count - 1] as RecycleItem;
230 if (prevFirstItem != null && target != null)
232 target.Position = new Position(
233 LayoutOrientation == Orientation.Vertical ? (prevFirstItem.Position.X - target.Size.Width) : prevFirstItem.Position.X,
234 LayoutOrientation == Orientation.Vertical ? prevFirstItem.Position.Y : (prevFirstItem.Position.Y - target.Size.Height)
236 target.DataIndex = target.DataIndex - Container.Children.Count;
237 target.SiblingOrder = 0;
246 PrevScrollPosition = scrollPosition;
252 /// Adjust scrolling position by own scrolling rules.
254 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
255 /// <since_tizen> 8 </since_tizen>
256 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
257 public override float CalculateCandidateScrollPosition(float scrollPosition)
259 return scrollPosition;
262 public override View RequestNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
264 View nextFocusedView = null;
265 int targetSibling = -1;
266 bool isHorizontal = LayoutOrientation == Orientation.Horizontal;
270 case View.FocusDirection.Left:
272 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder - 1 : currentFocusedView.SiblingOrder - Rows;
275 case View.FocusDirection.Right:
277 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder + 1 : currentFocusedView.SiblingOrder + Rows;
280 case View.FocusDirection.Up:
282 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder - Columns : currentFocusedView.SiblingOrder - 1;
285 case View.FocusDirection.Down:
287 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder + Columns : currentFocusedView.SiblingOrder + 1;
292 if (targetSibling > -1 && targetSibling < Container.Children.Count)
294 RecycleItem candidate = Container.Children[targetSibling] as RecycleItem;
295 if (candidate != null && candidate.DataIndex >= 0 && candidate.DataIndex < DataCount)
297 nextFocusedView = candidate;
301 return nextFocusedView;