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 linear 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 LinearRecycleLayoutManager : RecycleLayoutManager
31 private int firstVisibleItemIndex = -1;
32 private int lastVisibleItemIndex = -1;
34 private bool IsItemVisible(float scrollPosition, RecycleItem item)
37 View list = Container.GetParent() as View;
43 Vector2 visibleArea = new Vector2( Math.Abs(scrollPosition),
44 Math.Abs(scrollPosition) + (LayoutOrientation == Orientation.Horizontal?
45 list.Size.Width:list.Size.Height)
48 float firstCheckPoint = LayoutOrientation == Orientation.Horizontal? item.Position.X:item.Position.Y;
49 float secondCheckPoint = LayoutOrientation == Orientation.Horizontal?
50 firstCheckPoint + item.Size.Width:
51 firstCheckPoint + item.Size.Height;
53 // Tizen.Log.Error("NUI", "[1p] "+visibleArea.X+ " =< "+firstCheckPoint+" =< "+visibleArea.Y+" ==== \n");
54 // Tizen.Log.Error("NUI", "[2p] "+visibleArea.X+ " =< "+secondCheckPoint+" =< "+visibleArea.Y+" ==== \n");
56 result = (firstCheckPoint >= visibleArea.X && firstCheckPoint <= visibleArea.Y) || (secondCheckPoint >= visibleArea.X && secondCheckPoint <= visibleArea.Y);
62 /// This is called to find out where items are lain out according to current scroll position.
64 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
65 /// <since_tizen> 8 </since_tizen>
66 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
67 public override void Layout(float scrollPosition)
69 firstVisibleItemIndex = -1;
70 lastVisibleItemIndex = -1;
72 RecycleItem previousItem = null;
74 for(int i = 0 ; i < Container.Children.Count ; i++)
76 RecycleItem item = Container.Children[i] as RecycleItem;
78 if(previousItem != null && item != null)
80 item.Position = LayoutOrientation == Orientation.Horizontal?
82 previousItem.Position.X + (previousItem.CurrentSize.Width != 0 ?
83 previousItem.CurrentSize.Width:
84 previousItem.Size.Width),
89 previousItem.Position.Y + (previousItem.CurrentSize.Height != 0 ?
90 previousItem.CurrentSize.Height:
91 previousItem.Size.Height)
95 bool isVisible = IsItemVisible(scrollPosition, item);
99 firstVisibleItemIndex = firstVisibleItemIndex == -1? i : firstVisibleItemIndex;
100 lastVisibleItemIndex = i;
105 // Tizen.Log.Error("NUI","["+item.DataIndex+"] "+item.Position.Y+" ==== \n");
110 StepSize = LayoutOrientation == Orientation.Horizontal?ItemSize.Width:ItemSize.Height;
115 /// This is called to find out how much container size can be.
117 /// <since_tizen> 8 </since_tizen>
118 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
119 [EditorBrowsable(EditorBrowsableState.Never)]
120 public override float CalculateLayoutOrientationSize()
122 return StepSize * DataCount;
126 /// This is called to find out which items should be recycled according to current scroll position.
128 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
129 /// <returns>List of RecycleItems which should be recycled.</returns>
130 /// <since_tizen> 8 </since_tizen>
131 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
132 public override List<RecycleItem> Recycle(float scrollPosition)
134 List<RecycleItem> result = new List<RecycleItem>();
136 bool checkFront = (PrevScrollPosition - scrollPosition) > 0;
140 if(firstVisibleItemIndex > 3)
142 // Too many item is in front!!! move first item to back!!!!
143 RecycleItem target = Container.Children[0] as RecycleItem;
146 target.DataIndex = target.DataIndex + Container.Children.Count;
147 target.SiblingOrder = Container.Children.Count - 1;
155 if(lastVisibleItemIndex < Container.Children.Count - 3)
157 RecycleItem prevFirstItem = Container.Children[0] as RecycleItem;
158 RecycleItem target = Container.Children[Container.Children.Count - 1] as RecycleItem;
159 if (prevFirstItem != null && target != null)
161 target.Position = new Position(
162 LayoutOrientation == Orientation.Horizontal ? (prevFirstItem.Position.X - target.Size.Width) : prevFirstItem.Position.X,
163 LayoutOrientation == Orientation.Horizontal ? prevFirstItem.Position.Y : (prevFirstItem.Position.Y - target.Size.Height)
165 target.DataIndex = target.DataIndex - Container.Children.Count;
166 target.SiblingOrder = 0;
173 PrevScrollPosition = scrollPosition;
179 /// Adjust scrolling position by own scrolling rules.
181 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
182 /// <since_tizen> 8 </since_tizen>
183 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
184 public override float CalculateCandidateScrollPosition(float scrollPosition)
186 return scrollPosition;
189 public override View RequestNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
191 View nextFocusedView = null;
192 int targetSibling = -1;
193 bool isHorizontal = LayoutOrientation == Orientation.Horizontal;
197 case View.FocusDirection.Left :
199 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder - 1 : targetSibling;
202 case View.FocusDirection.Right :
204 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder + 1 : targetSibling;
207 case View.FocusDirection.Up :
209 targetSibling = isHorizontal ? targetSibling : currentFocusedView.SiblingOrder - 1;
212 case View.FocusDirection.Down :
214 targetSibling = isHorizontal ? targetSibling : currentFocusedView.SiblingOrder + 1;
219 if(targetSibling > -1 && targetSibling < Container.Children.Count)
221 RecycleItem candidate = Container.Children[targetSibling] as RecycleItem;
222 if(candidate != null && candidate.DataIndex >= 0 && candidate.DataIndex < DataCount)
224 nextFocusedView = candidate;
228 return nextFocusedView;