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 Tizen.NUI.Components;
19 using System.Collections.Generic;
20 using System.ComponentModel;
22 namespace Tizen.NUI.Wearable
25 /// [Draft] This class implements a grid box layout.
27 /// <since_tizen> 8 </since_tizen>
28 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
29 [EditorBrowsable(EditorBrowsableState.Never)]
30 public class GridRecycleLayoutManager : RecycleLayoutManager
35 /// [draft ]Get/Set the number of rows in the grid
37 /// <since_tizen> 8 </since_tizen>
38 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
39 [EditorBrowsable(EditorBrowsableState.Never)]
50 if (Container != null)
52 Layout(PrevScrollPosition);
57 private int columns = 1;
61 /// [Draft] Get/Set the number of columns in the grid
63 /// <since_tizen> 8 </since_tizen>
64 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
65 [EditorBrowsable(EditorBrowsableState.Never)]
76 if (Container != null)
78 Layout(PrevScrollPosition);
83 private int firstVisibleItemIndex = -1;
84 private int lastVisibleItemIndex = -1;
86 private bool IsItemVisible(float scrollPosition, RecycleItem item)
89 View list = Container.GetParent() as View;
94 Vector2 visibleArea = new Vector2(Math.Abs(scrollPosition),
95 Math.Abs(scrollPosition) + (LayoutOrientation == Orientation.Vertical ?
96 list.Size.Width : list.Size.Height)
99 float firstCheckPoint = LayoutOrientation == Orientation.Vertical ? item.Position.X : item.Position.Y;
100 float secondCheckPoint = LayoutOrientation == Orientation.Vertical ?
101 firstCheckPoint + item.Size.Width :
102 firstCheckPoint + item.Size.Height;
104 result = (firstCheckPoint >= visibleArea.X && firstCheckPoint <= visibleArea.Y) || (secondCheckPoint >= visibleArea.X && secondCheckPoint <= visibleArea.Y);
110 /// This is called to find out how much container size can be.
112 /// <since_tizen> 8 </since_tizen>
113 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
114 [EditorBrowsable(EditorBrowsableState.Never)]
115 public override float CalculateLayoutOrientationSize()
117 float orientationFactor = LayoutOrientation == Orientation.Vertical ? Rows : Columns;
118 return StepSize * (int)Math.Ceiling((double)DataCount / (double)orientationFactor);
123 /// This is called to find out where items are lain out according to current scroll position.
125 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
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 void Layout(float scrollPosition)
130 int itemInGroup = LayoutOrientation == Orientation.Vertical ? Rows : Columns;
131 firstVisibleItemIndex = -1;
132 lastVisibleItemIndex = -1;
134 RecycleItem previousItem = null;
136 for (int i = 0; i < Container.Children.Count; i++)
138 RecycleItem item = Container.Children[i] as RecycleItem;
140 if (previousItem != null && item != null)
142 item.Position = LayoutOrientation == Orientation.Vertical ?
144 (i % itemInGroup == 0 ?
145 previousItem.Position.X + (previousItem.CurrentSize.Width != 0 ?
146 previousItem.CurrentSize.Width :
147 previousItem.Size.Width) :
148 previousItem.Position.X),
149 (i % itemInGroup == 0 ?
151 previousItem.PositionY + (previousItem.CurrentSize.Height != 0 ?
152 previousItem.CurrentSize.Height :
153 previousItem.Size.Height))
156 (i % itemInGroup == 0 ?
158 previousItem.PositionX + (previousItem.CurrentSize.Width != 0 ?
159 previousItem.CurrentSize.Width :
160 previousItem.Size.Width)),
161 (i % itemInGroup == 0 ?
162 previousItem.Position.Y + (previousItem.CurrentSize.Height != 0 ?
163 previousItem.CurrentSize.Height :
164 previousItem.Size.Height) :
165 previousItem.Position.Y)
169 bool isVisible = IsItemVisible(scrollPosition, item);
173 firstVisibleItemIndex = firstVisibleItemIndex == -1 ? i : firstVisibleItemIndex;
174 lastVisibleItemIndex = i;
182 StepSize = LayoutOrientation == Orientation.Vertical ? ItemSize.Width : ItemSize.Height;
188 /// This is called to find out which items should be recycled according to current scroll position.
190 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
191 /// <returns>List of RecycleItems which should be recycled.</returns>
192 /// <since_tizen> 8 </since_tizen>
193 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
194 public override List<RecycleItem> Recycle(float scrollPosition)
196 List<RecycleItem> result = new List<RecycleItem>();
197 bool checkFront = (PrevScrollPosition - scrollPosition) > 0;
199 int itemInGroup = LayoutOrientation == Orientation.Vertical ? Rows : Columns;
203 int currentGroupNum = (int)(firstVisibleItemIndex / itemInGroup) + 1;
205 if (currentGroupNum > 2)
207 // Too many item is in front!!! move first item to back!!!!
208 for (int i = 0; i < itemInGroup; i++)
210 RecycleItem target = Container.Children[0] as RecycleItem;
213 target.DataIndex = target.DataIndex + Container.Children.Count;
214 target.SiblingOrder = Container.Children.Count - 1;
223 int currentGroupNum = (int)(lastVisibleItemIndex / itemInGroup) + 1;
225 if (currentGroupNum < (int)(Container.Children.Count / itemInGroup) - 3)
227 for (int i = 0; i < itemInGroup; i++)
229 RecycleItem prevFirstItem = Container.Children[itemInGroup] as RecycleItem;
230 RecycleItem target = Container.Children[Container.Children.Count - 1] as RecycleItem;
231 if (prevFirstItem != null && target != null)
233 target.Position = new Position(
234 LayoutOrientation == Orientation.Vertical ? (prevFirstItem.Position.X - target.Size.Width) : prevFirstItem.Position.X,
235 LayoutOrientation == Orientation.Vertical ? prevFirstItem.Position.Y : (prevFirstItem.Position.Y - target.Size.Height)
237 target.DataIndex = target.DataIndex - Container.Children.Count;
238 target.SiblingOrder = 0;
247 PrevScrollPosition = scrollPosition;
253 /// Adjust scrolling position by own scrolling rules.
255 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
256 /// <since_tizen> 8 </since_tizen>
257 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
258 public override float CalculateCandidateScrollPosition(float scrollPosition)
260 return scrollPosition;
263 public override View RequestNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
265 View nextFocusedView = null;
266 int targetSibling = -1;
267 bool isHorizontal = LayoutOrientation == Orientation.Horizontal;
271 case View.FocusDirection.Left:
273 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder - 1 : currentFocusedView.SiblingOrder - Rows;
276 case View.FocusDirection.Right:
278 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder + 1 : currentFocusedView.SiblingOrder + Rows;
281 case View.FocusDirection.Up:
283 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder - Columns : currentFocusedView.SiblingOrder - 1;
286 case View.FocusDirection.Down:
288 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder + Columns : currentFocusedView.SiblingOrder + 1;
293 if (targetSibling > -1 && targetSibling < Container.Children.Count)
295 RecycleItem candidate = Container.Children[targetSibling] as RecycleItem;
296 if (candidate != null && candidate.DataIndex >= 0 && candidate.DataIndex < DataCount)
298 nextFocusedView = candidate;
302 return nextFocusedView;