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 linear 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 LinearRecycleLayoutManager : RecycleLayoutManager
32 private int firstVisibleItemIndex = -1;
33 private int lastVisibleItemIndex = -1;
35 private bool IsItemVisible(float scrollPosition, RecycleItem item)
38 View list = Container.GetParent() as View;
44 Vector2 visibleArea = new Vector2(Math.Abs(scrollPosition),
45 Math.Abs(scrollPosition) + (LayoutOrientation == Orientation.Horizontal ?
46 list.Size.Width : list.Size.Height)
49 float firstCheckPoint = LayoutOrientation == Orientation.Horizontal ? item.Position.X : item.Position.Y;
50 float secondCheckPoint = LayoutOrientation == Orientation.Horizontal ?
51 firstCheckPoint + item.Size.Width :
52 firstCheckPoint + item.Size.Height;
54 // Tizen.Log.Error("NUI", "[1p] "+visibleArea.X+ " =< "+firstCheckPoint+" =< "+visibleArea.Y+" ==== \n");
55 // Tizen.Log.Error("NUI", "[2p] "+visibleArea.X+ " =< "+secondCheckPoint+" =< "+visibleArea.Y+" ==== \n");
57 result = (firstCheckPoint >= visibleArea.X && firstCheckPoint <= visibleArea.Y) || (secondCheckPoint >= visibleArea.X && secondCheckPoint <= visibleArea.Y);
63 /// This is called to find out where items are lain out according to current scroll position.
65 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
66 /// <since_tizen> 8 </since_tizen>
67 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
68 public override void Layout(float scrollPosition)
70 firstVisibleItemIndex = -1;
71 lastVisibleItemIndex = -1;
73 RecycleItem previousItem = null;
75 for (int i = 0; i < Container.Children.Count; i++)
77 RecycleItem item = Container.Children[i] as RecycleItem;
79 if (previousItem != null && item != null)
81 item.Position = LayoutOrientation == Orientation.Horizontal ?
83 previousItem.Position.X + (previousItem.CurrentSize.Width != 0 ?
84 previousItem.CurrentSize.Width :
85 previousItem.Size.Width),
90 previousItem.Position.Y + (previousItem.CurrentSize.Height != 0 ?
91 previousItem.CurrentSize.Height :
92 previousItem.Size.Height)
96 bool isVisible = IsItemVisible(scrollPosition, item);
100 firstVisibleItemIndex = firstVisibleItemIndex == -1 ? i : firstVisibleItemIndex;
101 lastVisibleItemIndex = i;
106 // Tizen.Log.Error("NUI","["+item.DataIndex+"] "+item.Position.Y+" ==== \n");
111 StepSize = LayoutOrientation == Orientation.Horizontal ? ItemSize.Width : ItemSize.Height;
116 /// This is called to find out how much container size can be.
118 /// <since_tizen> 8 </since_tizen>
119 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
120 [EditorBrowsable(EditorBrowsableState.Never)]
121 public override float CalculateLayoutOrientationSize()
123 return StepSize * DataCount;
127 /// This is called to find out which items should be recycled according to current scroll position.
129 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
130 /// <returns>List of RecycleItems which should be recycled.</returns>
131 /// <since_tizen> 8 </since_tizen>
132 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
133 public override List<RecycleItem> Recycle(float scrollPosition)
135 List<RecycleItem> result = new List<RecycleItem>();
137 bool checkFront = (PrevScrollPosition - scrollPosition) > 0;
141 if (firstVisibleItemIndex > 3)
143 // Too many item is in front!!! move first item to back!!!!
144 RecycleItem target = Container.Children[0] as RecycleItem;
147 target.DataIndex = target.DataIndex + Container.Children.Count;
148 target.SiblingOrder = Container.Children.Count - 1;
156 if (lastVisibleItemIndex < Container.Children.Count - 3)
158 RecycleItem prevFirstItem = Container.Children[0] as RecycleItem;
159 RecycleItem target = Container.Children[Container.Children.Count - 1] as RecycleItem;
160 if (prevFirstItem != null && target != null)
162 target.Position = new Position(
163 LayoutOrientation == Orientation.Horizontal ? (prevFirstItem.Position.X - target.Size.Width) : prevFirstItem.Position.X,
164 LayoutOrientation == Orientation.Horizontal ? prevFirstItem.Position.Y : (prevFirstItem.Position.Y - target.Size.Height)
166 target.DataIndex = target.DataIndex - Container.Children.Count;
167 target.SiblingOrder = 0;
174 PrevScrollPosition = scrollPosition;
180 /// Adjust scrolling position by own scrolling rules.
182 /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
183 /// <since_tizen> 8 </since_tizen>
184 /// This may be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API
185 public override float CalculateCandidateScrollPosition(float scrollPosition)
187 return scrollPosition;
191 public override View RequestNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
193 View nextFocusedView = null;
194 int targetSibling = -1;
195 bool isHorizontal = LayoutOrientation == Orientation.Horizontal;
199 case View.FocusDirection.Left:
201 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder - 1 : targetSibling;
204 case View.FocusDirection.Right:
206 targetSibling = isHorizontal ? currentFocusedView.SiblingOrder + 1 : targetSibling;
209 case View.FocusDirection.Up:
211 targetSibling = isHorizontal ? targetSibling : currentFocusedView.SiblingOrder - 1;
214 case View.FocusDirection.Down:
216 targetSibling = isHorizontal ? targetSibling : currentFocusedView.SiblingOrder + 1;
223 if (targetSibling > -1 && targetSibling < Container.Children.Count)
225 RecycleItem candidate = Container.Children[targetSibling] as RecycleItem;
226 if (candidate != null && candidate.DataIndex >= 0 && candidate.DataIndex < DataCount)
228 nextFocusedView = candidate;
232 return nextFocusedView;